Skip to content

Commit 461b2f9

Browse files
authored
Merge pull request #512 from DevKor-github/codexd/fix-default-preparation-transition
[codex] Smooth default preparation edit transition
2 parents 02b2abc + ae5cf63 commit 461b2f9

2 files changed

Lines changed: 312 additions & 84 deletions

File tree

lib/presentation/my_page/preparation_spare_time_edit/preparation_spare_time_edit_screen.dart

Lines changed: 156 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,21 @@ class PreparationSpareTimeEditScreen extends StatelessWidget {
1414

1515
@override
1616
Widget build(BuildContext context) {
17-
return BlocProvider<DefaultPreparationSpareTimeFormBloc>(
18-
create: (context) {
19-
final spareTime =
20-
context.read<AuthBloc>().state.user.spareTimeOrNull ??
21-
Duration.zero;
22-
return getIt.get<DefaultPreparationSpareTimeFormBloc>()
23-
..add(FormEditRequested(spareTime: spareTime));
24-
},
17+
return MultiBlocProvider(
18+
providers: [
19+
BlocProvider<DefaultPreparationSpareTimeFormBloc>(
20+
create: (context) {
21+
final spareTime =
22+
context.read<AuthBloc>().state.user.spareTimeOrNull ??
23+
Duration.zero;
24+
return getIt.get<DefaultPreparationSpareTimeFormBloc>()
25+
..add(FormEditRequested(spareTime: spareTime));
26+
},
27+
),
28+
BlocProvider<PreparationFormBloc>(
29+
create: (context) => getIt.get<PreparationFormBloc>(),
30+
),
31+
],
2532
child: const _PreparationSpareTimeEditView(),
2633
);
2734
}
@@ -32,95 +39,153 @@ class _PreparationSpareTimeEditView extends StatelessWidget {
3239

3340
@override
3441
Widget build(BuildContext context) {
35-
return BlocBuilder<
42+
return BlocListener<
3643
DefaultPreparationSpareTimeFormBloc,
3744
DefaultPreparationSpareTimeFormState
3845
>(
39-
builder: (context, state) {
40-
if (state.status == DefaultPreparationSpareTimeStatus.success) {
41-
return BlocProvider<PreparationFormBloc>(
42-
create: (context) => getIt.get<PreparationFormBloc>()
43-
..add(
44-
PreparationFormEditRequested(
45-
preparationEntity: state.preparation!,
46-
),
47-
),
48-
child: BlocBuilder<PreparationFormBloc, PreparationFormState>(
46+
listenWhen: (previous, current) =>
47+
current.status == DefaultPreparationSpareTimeStatus.success &&
48+
current.preparation != null &&
49+
previous.preparation != current.preparation,
50+
listener: (context, state) {
51+
context.read<PreparationFormBloc>().add(
52+
PreparationFormEditRequested(preparationEntity: state.preparation!),
53+
);
54+
},
55+
child: Scaffold(
56+
appBar: AppBar(
57+
elevation: 0,
58+
shadowColor: Colors.transparent,
59+
scrolledUnderElevation: 0,
60+
backgroundColor: Colors.transparent,
61+
leading: IconButton(
62+
icon: Icon(
63+
Icons.arrow_back_ios_rounded,
64+
color: Theme.of(context).colorScheme.outlineVariant,
65+
),
66+
onPressed: () => context.pop(),
67+
),
68+
title: Text(
69+
AppLocalizations.of(context)!.editDefaultPreparation,
70+
style: Theme.of(context).textTheme.titleLarge,
71+
),
72+
actions: [
73+
BlocBuilder<
74+
DefaultPreparationSpareTimeFormBloc,
75+
DefaultPreparationSpareTimeFormState
76+
>(
77+
buildWhen: (previous, current) =>
78+
previous.status != current.status ||
79+
previous.spareTime != current.spareTime,
4980
builder: (context, state2) {
50-
return Scaffold(
51-
appBar: AppBar(
52-
elevation: 0,
53-
shadowColor: Colors.transparent,
54-
scrolledUnderElevation: 0,
55-
backgroundColor: Colors.transparent,
56-
leading: IconButton(
57-
icon: Icon(
58-
Icons.arrow_back_ios_rounded,
59-
color: Theme.of(context).colorScheme.outlineVariant,
60-
),
61-
onPressed: () => context.pop(),
62-
),
63-
title: Text(
64-
AppLocalizations.of(context)!.editDefaultPreparation,
65-
style: Theme.of(context).textTheme.titleLarge,
66-
),
67-
actions: [
68-
TextButton(
69-
onPressed: state2.isValid
70-
? () {
71-
context
72-
.read<DefaultPreparationSpareTimeFormBloc>()
73-
.add(
74-
FormSubmitted(
75-
note: '',
76-
preparation: state2
77-
.toPreparationEntity(),
78-
),
79-
);
80-
context.pop();
81-
}
82-
: null,
83-
child: Text(AppLocalizations.of(context)!.ok),
84-
),
85-
],
86-
bottom: const PreferredSize(
87-
preferredSize: Size.fromHeight(33),
88-
child: SizedBox(height: 33),
89-
),
90-
),
91-
body: SafeArea(
92-
child: Padding(
93-
padding: const EdgeInsets.symmetric(horizontal: 16.0),
94-
child: Column(
95-
children: [
96-
SizedBox(
97-
width: double.infinity,
98-
child: _SpareTimeSection(
99-
spareTime: state.spareTime!,
100-
),
101-
),
102-
SizedBox(height: 42.0),
103-
Expanded(
104-
child: _PreparationSection(
105-
preparationNameState: state2,
106-
),
107-
),
108-
],
109-
),
110-
),
111-
),
81+
return BlocBuilder<PreparationFormBloc, PreparationFormState>(
82+
buildWhen: (previous, current) =>
83+
previous.isValid != current.isValid,
84+
builder: (context, preparationState) {
85+
return TextButton(
86+
onPressed:
87+
state2.isReadyForEditing && preparationState.isValid
88+
? () {
89+
context
90+
.read<DefaultPreparationSpareTimeFormBloc>()
91+
.add(
92+
FormSubmitted(
93+
note: '',
94+
preparation: preparationState
95+
.toPreparationEntity(),
96+
),
97+
);
98+
context.pop();
99+
}
100+
: null,
101+
child: Text(AppLocalizations.of(context)!.ok),
102+
);
103+
},
112104
);
113105
},
114106
),
115-
);
116-
}
107+
],
108+
bottom: const PreferredSize(
109+
preferredSize: Size.fromHeight(33),
110+
child: SizedBox(height: 33),
111+
),
112+
),
113+
body: const SafeArea(child: _PreparationSpareTimeEditBody()),
114+
),
115+
);
116+
}
117+
}
117118

118-
return const Center(child: CircularProgressIndicator());
119+
class _PreparationSpareTimeEditBody extends StatelessWidget {
120+
const _PreparationSpareTimeEditBody();
121+
122+
@override
123+
Widget build(BuildContext context) {
124+
return BlocBuilder<
125+
DefaultPreparationSpareTimeFormBloc,
126+
DefaultPreparationSpareTimeFormState
127+
>(
128+
buildWhen: (previous, current) =>
129+
previous.status != current.status ||
130+
previous.spareTime != current.spareTime ||
131+
previous.preparation != current.preparation,
132+
builder: (context, state) {
133+
return AnimatedSwitcher(
134+
duration: const Duration(milliseconds: 180),
135+
switchInCurve: Curves.easeOutCubic,
136+
switchOutCurve: Curves.easeInCubic,
137+
child: state.isReadyForEditing
138+
? _PreparationSpareTimeEditContent(
139+
key: const ValueKey('preparation_spare_time_form'),
140+
spareTime: state.spareTime!,
141+
)
142+
: const _PreparationSpareTimeEditLoading(
143+
key: ValueKey('preparation_spare_time_loading'),
144+
),
145+
);
119146
},
120147
);
121148
}
122149
}
123150

151+
class _PreparationSpareTimeEditLoading extends StatelessWidget {
152+
const _PreparationSpareTimeEditLoading({super.key});
153+
154+
@override
155+
Widget build(BuildContext context) {
156+
return const Center(child: CircularProgressIndicator());
157+
}
158+
}
159+
160+
class _PreparationSpareTimeEditContent extends StatelessWidget {
161+
const _PreparationSpareTimeEditContent({super.key, required this.spareTime});
162+
163+
final Duration spareTime;
164+
165+
@override
166+
Widget build(BuildContext context) {
167+
return Padding(
168+
padding: const EdgeInsets.symmetric(horizontal: 16.0),
169+
child: Column(
170+
children: [
171+
SizedBox(
172+
width: double.infinity,
173+
child: _SpareTimeSection(spareTime: spareTime),
174+
),
175+
SizedBox(height: 42.0),
176+
Expanded(
177+
child: BlocBuilder<PreparationFormBloc, PreparationFormState>(
178+
builder: (context, state) {
179+
return _PreparationSection(preparationNameState: state);
180+
},
181+
),
182+
),
183+
],
184+
),
185+
);
186+
}
187+
}
188+
124189
class _SpareTimeSection extends StatelessWidget {
125190
const _SpareTimeSection({required this.spareTime});
126191

@@ -159,6 +224,13 @@ class _SpareTimeSection extends StatelessWidget {
159224
}
160225
}
161226

227+
extension on DefaultPreparationSpareTimeFormState {
228+
bool get isReadyForEditing =>
229+
status == DefaultPreparationSpareTimeStatus.success &&
230+
spareTime != null &&
231+
preparation != null;
232+
}
233+
162234
class _PreparationSection extends StatelessWidget {
163235
const _PreparationSection({required this.preparationNameState});
164236

0 commit comments

Comments
 (0)