Skip to content

Commit 9fdcd1e

Browse files
committed
feat!: asynced custom alert dialog
This commit refactored `CustomAlertDialog`, use the sync one in general use case and `.future` constructor if content is building from Future. * `scrollable` parameter is removed, now the body content always wrapped in SingleChildScrollView. * Now the content MUST never wrapped in infinite height widget, e.g. ListView and SingleChildScrollView. * Fixed FutureBuilder rebuilt by seperating body content into the body stateful widget. * Fixed incorrect scroll postion. * Fixed initial Divider state.
1 parent d6107f6 commit 9fdcd1e

24 files changed

+344
-330
lines changed

lib/features/editor/widgets/image_dialog.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ class _ImageDialogState extends State<_ImageDialog> with LoggerMixin, SingleTick
178178
Widget build(BuildContext context) {
179179
final tr = context.t.bbcodeEditor.image;
180180

181-
return CustomAlertDialog(
181+
return CustomAlertDialog.sync(
182182
clipBehavior: Clip.hardEdge,
183183
title: Column(
184184
crossAxisAlignment: CrossAxisAlignment.start,

lib/features/editor/widgets/url_dialog.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ class _UrlDialogState extends State<UrlDialog> {
9898
@override
9999
Widget build(BuildContext context) {
100100
final tr = context.t.bbcodeEditor.url;
101-
return CustomAlertDialog(
101+
return CustomAlertDialog.sync(
102102
clipBehavior: Clip.antiAlias,
103103
title: Text(context.t.bbcodeEditor.url.title),
104104
content: Form(

lib/features/editor/widgets/username_picker_dialog.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,8 @@ class _UsernamePickerDialogState extends State<_UsernamePickerDialog> with Logge
190190
BlocProvider(create: (context) => UserMentionCubit(context.repo())..recommendFriend()),
191191
],
192192
child: BlocBuilder<UserMentionCubit, UserMentionState>(
193-
builder: (context, state) => CustomAlertDialog(
193+
builder: (context, state) => CustomAlertDialog.sync(
194194
title: Text(tr.title),
195-
scrollable: true,
196195
content: Form(
197196
key: formKey,
198197
child: Column(

lib/features/homepage/widgets/user_operation_dialog.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,14 @@ class UserOperationDialog extends StatelessWidget with LoggerMixin {
4545

4646
final tr = context.t.homepage.welcome;
4747

48-
return CustomAlertDialog(
48+
return CustomAlertDialog.sync(
4949
title: Row(
5050
children: [
5151
HeroUserAvatar(username: username, avatarUrl: avatarUrl, heroTag: username, minRadius: 30),
5252
sizedBoxW12H12,
5353
Expanded(child: SingleLineText(username, style: Theme.of(context).textTheme.titleLarge)),
5454
],
5555
),
56-
scrollable: true,
5756
content: Column(
5857
mainAxisSize: MainAxisSize.min,
5958
children: [
Lines changed: 17 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import 'dart:math' as math;
2-
31
import 'package:flutter/material.dart';
42
import 'package:tsdm_client/i18n/strings.g.dart';
53
import 'package:tsdm_client/widgets/custom_alert_dialog.dart';
@@ -28,53 +26,30 @@ class JumpPageDialog extends StatelessWidget {
2826
final choicesList = List.generate(max - min + 1, (index) {
2927
return min + index;
3028
}).toList();
31-
return CustomAlertDialog(
29+
return CustomAlertDialog.sync(
3230
title: Text(context.t.jumpDialog.title),
3331
// FIXME: Here should handle better when both large mount or small mount
3432
// of choices.
3533
// Issue is that Column will junk is choices are too many and ListView
3634
// fills all height even there are only few choices.
37-
content: choicesList.length <= 30
38-
? SingleChildScrollView(
39-
child: Column(
40-
children: choicesList
41-
.map(
42-
(e) => RadioListTile(
43-
title: Text('$e'),
44-
value: e,
45-
groupValue: v,
46-
onChanged: (value) {
47-
if (value == null) {
48-
return;
49-
}
50-
v = value;
51-
Navigator.pop(context, v);
52-
},
53-
),
54-
)
55-
.toList(),
56-
),
57-
)
58-
: SizedBox(
59-
width: math.min(MediaQuery.of(context).size.width * 0.75, 200),
60-
child: ListView.builder(
61-
itemCount: choicesList.length,
62-
itemBuilder: (context, index) {
63-
return RadioListTile(
64-
title: Text('${choicesList[index]}'),
65-
value: choicesList[index],
66-
groupValue: v,
67-
onChanged: (value) {
68-
if (value == null) {
69-
return;
70-
}
71-
v = value;
72-
Navigator.pop(context, v);
73-
},
74-
);
35+
content: Column(
36+
children: choicesList
37+
.map(
38+
(e) => RadioListTile(
39+
title: Text('$e'),
40+
value: e,
41+
groupValue: v,
42+
onChanged: (value) {
43+
if (value == null) {
44+
return;
45+
}
46+
v = value;
47+
Navigator.pop(context, v);
7548
},
7649
),
77-
),
50+
)
51+
.toList(),
52+
),
7853
);
7954
}
8055
}

lib/features/multi_user/widgets/manage_user_dialog.dart

Lines changed: 45 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class _ManageUserDialog extends StatelessWidget with LoggerMixin {
4444
@override
4545
Widget build(BuildContext context) {
4646
final tr = context.t.manageAccountPage.switchAccount.dialog;
47-
return CustomAlertDialog(
47+
return CustomAlertDialog.sync(
4848
clipBehavior: Clip.hardEdge,
4949
title: Row(
5050
children: [
@@ -53,54 +53,52 @@ class _ManageUserDialog extends StatelessWidget with LoggerMixin {
5353
Expanded(child: SingleLineText(userInfo.username!, style: Theme.of(context).textTheme.titleLarge)),
5454
],
5555
),
56-
content: SingleChildScrollView(
57-
child: Column(
58-
children: [
59-
ListTile(
60-
title: Text(tr.switchAccount),
61-
onTap: () async {
62-
var times = 10;
63-
while (context.read<AutoNotificationCubit>().pause('switch user')) {
64-
info('switch user is waiting for auto sync lock... $times');
65-
times -= 1;
66-
await Future<void>.delayed(const Duration(milliseconds: 300));
67-
if (times <= 0 || !context.mounted) {
68-
info('auto sync lock timeout or canceled, do not switch user');
69-
return;
70-
}
71-
}
72-
context.read<SwitchUserBloc>().add(SwitchUserStartRequested(userInfo));
73-
context.pop();
74-
},
75-
),
76-
ListTile(
77-
title: Text(tr.clearLoginStatus.title),
78-
subtitle: Text(tr.clearLoginStatus.detail),
79-
enabled: userInfo.uid != null,
80-
onTap: () async {
81-
await getIt.get<StorageProvider>().deleteCookieByUid(userInfo.uid!);
82-
if (!context.mounted) {
83-
return;
84-
}
85-
context.pop();
86-
},
87-
),
88-
ListTile(
89-
title: Text(tr.loginAgain.title),
90-
subtitle: Text(tr.loginAgain.detail),
91-
onTap: () async {
92-
await context.pushNamed(
93-
ScreenPaths.login,
94-
queryParameters: {if (userInfo.username != null) 'username': '${userInfo.username}'},
95-
);
96-
if (!context.mounted) {
56+
content: Column(
57+
children: [
58+
ListTile(
59+
title: Text(tr.switchAccount),
60+
onTap: () async {
61+
var times = 10;
62+
while (context.read<AutoNotificationCubit>().pause('switch user')) {
63+
info('switch user is waiting for auto sync lock... $times');
64+
times -= 1;
65+
await Future<void>.delayed(const Duration(milliseconds: 300));
66+
if (times <= 0 || !context.mounted) {
67+
info('auto sync lock timeout or canceled, do not switch user');
9768
return;
9869
}
99-
context.pop();
100-
},
101-
),
102-
],
103-
),
70+
}
71+
context.read<SwitchUserBloc>().add(SwitchUserStartRequested(userInfo));
72+
context.pop();
73+
},
74+
),
75+
ListTile(
76+
title: Text(tr.clearLoginStatus.title),
77+
subtitle: Text(tr.clearLoginStatus.detail),
78+
enabled: userInfo.uid != null,
79+
onTap: () async {
80+
await getIt.get<StorageProvider>().deleteCookieByUid(userInfo.uid!);
81+
if (!context.mounted) {
82+
return;
83+
}
84+
context.pop();
85+
},
86+
),
87+
ListTile(
88+
title: Text(tr.loginAgain.title),
89+
subtitle: Text(tr.loginAgain.detail),
90+
onTap: () async {
91+
await context.pushNamed(
92+
ScreenPaths.login,
93+
queryParameters: {if (userInfo.username != null) 'username': '${userInfo.username}'},
94+
);
95+
if (!context.mounted) {
96+
return;
97+
}
98+
context.pop();
99+
},
100+
),
101+
],
104102
),
105103
);
106104
}

lib/features/parse_url/widgets/parse_url_dialog.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class _ParseUrlDialogState extends State<_ParseUrlDialog> {
6262
@override
6363
Widget build(BuildContext context) {
6464
final tr = context.t.parseUrlDialog;
65-
return CustomAlertDialog(
65+
return CustomAlertDialog.sync(
6666
title: Text(tr.title),
6767
content: Column(
6868
mainAxisSize: MainAxisSize.min,

lib/features/post/widgets/input_price_dialog.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class _InputPriceDialogState extends State<_InputPriceDialog> {
5252
@override
5353
Widget build(BuildContext context) {
5454
final tr = context.t.postEditPage.priceDialog;
55-
return CustomAlertDialog(
55+
return CustomAlertDialog.sync(
5656
title: Text(tr.title),
5757
content: Form(
5858
key: formKey,

lib/features/post/widgets/select_perm_dialog.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class _SelectPermDialogState extends State<_SelectPermDialog> {
3939

4040
@override
4141
Widget build(BuildContext context) {
42-
return CustomAlertDialog(
42+
return CustomAlertDialog.sync(
4343
title: Text(context.t.postEditPage.permDialog.title),
4444
content: Column(
4545
children: widget.permList
@@ -59,7 +59,6 @@ class _SelectPermDialogState extends State<_SelectPermDialog> {
5959
)
6060
.toList(),
6161
),
62-
scrollable: true,
6362
);
6463
}
6564
}

lib/features/rate/view/rate_post_page.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,8 @@ class _RatePostPageState extends State<RatePostPage> with LoggerMixin {
153153
context: context,
154154
builder: (_) => RootPage(
155155
DialogPaths.selectRateReason,
156-
CustomAlertDialog(
156+
CustomAlertDialog.sync(
157157
title: Text(tr.reason),
158-
scrollable: true,
159158
content: Column(
160159
children: state.info!.defaultReasonList
161160
.map(

0 commit comments

Comments
 (0)