Skip to content

Commit 20391bf

Browse files
authored
chore: revamp database setting action sheets (#4570)
* chore: revamp database setting action sheets * chore: field picker improvement * chore: fix comments
1 parent 9d28360 commit 20391bf

File tree

14 files changed

+329
-522
lines changed

14 files changed

+329
-522
lines changed

frontend/appflowy_flutter/lib/mobile/presentation/base/app_bar_actions.dart

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,39 @@ class AppBarDoneButton extends StatelessWidget {
8585
}
8686
}
8787

88+
class AppBarFilledDoneButton extends StatelessWidget {
89+
const AppBarFilledDoneButton({super.key, required this.onTap});
90+
91+
final VoidCallback onTap;
92+
93+
@override
94+
Widget build(BuildContext context) {
95+
return Padding(
96+
padding: const EdgeInsets.fromLTRB(8, 4, 8, 8),
97+
child: TextButton(
98+
style: TextButton.styleFrom(
99+
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 5),
100+
shape: RoundedRectangleBorder(
101+
borderRadius: BorderRadius.circular(10),
102+
),
103+
elevation: 0,
104+
visualDensity: VisualDensity.compact,
105+
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
106+
enableFeedback: true,
107+
backgroundColor: Theme.of(context).primaryColor,
108+
),
109+
onPressed: onTap,
110+
child: FlowyText.medium(
111+
LocaleKeys.button_done.tr(),
112+
fontSize: 16,
113+
color: Theme.of(context).colorScheme.onPrimary,
114+
overflow: TextOverflow.ellipsis,
115+
),
116+
),
117+
);
118+
}
119+
}
120+
88121
class AppBarMoreButton extends StatelessWidget {
89122
const AppBarMoreButton({
90123
super.key,

frontend/appflowy_flutter/lib/mobile/presentation/bottom_sheet/bottom_sheet.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ export 'bottom_sheet_drag_handler.dart';
44
export 'bottom_sheet_rename_widget.dart';
55
export 'bottom_sheet_view_item.dart';
66
export 'bottom_sheet_view_item_body.dart';
7-
export 'bottom_sheet_view_item_header.dart';
87
export 'bottom_sheet_view_page.dart';
98
export 'default_mobile_action_pane.dart';
109
export 'show_mobile_bottom_sheet.dart';

frontend/appflowy_flutter/lib/mobile/presentation/bottom_sheet/bottom_sheet_view_item_header.dart

Lines changed: 0 additions & 59 deletions
This file was deleted.

frontend/appflowy_flutter/lib/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ import 'package:flutter/material.dart';
77
Future<T?> showMobileBottomSheet<T>(
88
BuildContext context, {
99
required WidgetBuilder builder,
10+
bool useSafeArea = true,
1011
bool isDragEnabled = true,
1112
bool showDragHandle = false,
1213
bool showHeader = false,
1314
// this field is only used if showHeader is true
15+
bool showBackButton = false,
1416
bool showCloseButton = false,
1517
// this field is only used if showHeader is true
1618
String title = '',
@@ -20,7 +22,7 @@ Future<T?> showMobileBottomSheet<T>(
2022
bool useRootNavigator = false,
2123
ShapeBorder? shape,
2224
// the padding of the content, the padding of the header area is fixed
23-
EdgeInsets padding = const EdgeInsets.all(0.0),
25+
EdgeInsets padding = EdgeInsets.zero,
2426
Color? backgroundColor,
2527
BoxConstraints? constraints,
2628
Color? barrierColor,
@@ -32,10 +34,11 @@ Future<T?> showMobileBottomSheet<T>(
3234
double maxChildSize = 0.8,
3335
double initialChildSize = 0.51,
3436
}) async {
35-
assert(() {
36-
if (showCloseButton || title.isNotEmpty) assert(showHeader);
37-
return true;
38-
}());
37+
assert(
38+
showHeader ||
39+
title.isEmpty && !showCloseButton && !showBackButton && !showDoneButton,
40+
);
41+
assert(!(showCloseButton && showBackButton));
3942

4043
shape ??= const RoundedRectangleBorder(
4144
borderRadius: BorderRadius.vertical(
@@ -83,6 +86,7 @@ Future<T?> showMobileBottomSheet<T>(
8386
children.add(
8487
_Header(
8588
showCloseButton: showCloseButton,
89+
showBackButton: showBackButton,
8690
showDoneButton: showDoneButton,
8791
title: title,
8892
),
@@ -147,23 +151,30 @@ Future<T?> showMobileBottomSheet<T>(
147151
VSpace(MediaQuery.of(context).padding.bottom == 0 ? 28.0 : 16.0),
148152
);
149153

150-
return SafeArea(
151-
child: Column(
152-
mainAxisSize: MainAxisSize.min,
153-
children: children,
154-
),
155-
);
154+
return useSafeArea
155+
? SafeArea(
156+
child: Column(
157+
mainAxisSize: MainAxisSize.min,
158+
children: children,
159+
),
160+
)
161+
: Column(
162+
mainAxisSize: MainAxisSize.min,
163+
children: children,
164+
);
156165
},
157166
);
158167
}
159168

160169
class _Header extends StatelessWidget {
161170
const _Header({
171+
required this.showBackButton,
162172
required this.showCloseButton,
163173
required this.title,
164174
required this.showDoneButton,
165175
});
166176

177+
final bool showBackButton;
167178
final bool showCloseButton;
168179
final String title;
169180
final bool showDoneButton;
@@ -176,6 +187,11 @@ class _Header extends StatelessWidget {
176187
height: 44.0, // the height of the header area is fixed
177188
child: Stack(
178189
children: [
190+
if (showBackButton)
191+
const Align(
192+
alignment: Alignment.centerLeft,
193+
child: AppBarBackButton(),
194+
),
179195
if (showCloseButton)
180196
const Align(
181197
alignment: Alignment.centerLeft,

frontend/appflowy_flutter/lib/mobile/presentation/database/field/mobile_field_bottom_sheets.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,17 @@ void showQuickEditField(
128128
/// Display a list of fields in the current database that users can choose from.
129129
Future<String?> showFieldPicker(
130130
BuildContext context,
131+
String title,
131132
String? selectedFieldId,
132133
FieldController fieldController,
133134
bool Function(FieldInfo fieldInfo) filterBy,
134135
) {
135136
return showMobileBottomSheet<String>(
136137
context,
138+
showDivider: false,
137139
builder: (context) {
138140
return MobileFieldPickerList(
141+
title: title,
139142
selectedFieldId: selectedFieldId,
140143
fieldController: fieldController,
141144
filterBy: filterBy,

frontend/appflowy_flutter/lib/mobile/presentation/database/field/mobile_field_picker_list.dart

Lines changed: 59 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11
import 'package:appflowy/generated/flowy_svgs.g.dart';
2-
import 'package:appflowy/generated/locale_keys.g.dart';
2+
import 'package:appflowy/mobile/presentation/base/app_bar_actions.dart';
33
import 'package:appflowy/mobile/presentation/widgets/flowy_option_tile.dart';
44
import 'package:appflowy/plugins/base/drag_handler.dart';
55
import 'package:appflowy/plugins/database/application/field/field_controller.dart';
66
import 'package:appflowy/plugins/database/application/field/field_info.dart';
77
import 'package:appflowy/util/field_type_extension.dart';
8-
import 'package:easy_localization/easy_localization.dart';
98
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
109
import 'package:flutter/material.dart';
1110
import 'package:go_router/go_router.dart';
1211

1312
class MobileFieldPickerList extends StatefulWidget {
1413
MobileFieldPickerList({
1514
super.key,
15+
required this.title,
1616
required this.selectedFieldId,
1717
required FieldController fieldController,
1818
required bool Function(FieldInfo fieldInfo) filterBy,
1919
}) : fields = fieldController.fieldInfos.where(filterBy).toList();
2020

21+
final String title;
2122
final String? selectedFieldId;
2223
final List<FieldInfo> fields;
2324

@@ -36,87 +37,79 @@ class _MobileFieldPickerListState extends State<MobileFieldPickerList> {
3637

3738
@override
3839
Widget build(BuildContext context) {
39-
return Column(
40-
children: [
41-
const Center(child: DragHandler()),
42-
_Header(newFieldId: newFieldId),
43-
Expanded(
44-
child: ListView.builder(
45-
itemCount: widget.fields.length,
46-
itemBuilder: (context, index) => _FieldButton(
47-
field: widget.fields[index],
48-
showTopBorder: index == 0,
49-
isSelected: widget.fields[index].id == newFieldId,
50-
onSelect: (fieldId) => setState(() => newFieldId = fieldId),
40+
return DraggableScrollableSheet(
41+
expand: false,
42+
snap: true,
43+
initialChildSize: 0.98,
44+
minChildSize: 0.98,
45+
maxChildSize: 0.98,
46+
builder: (context, scrollController) {
47+
return Column(
48+
mainAxisSize: MainAxisSize.min,
49+
children: [
50+
const DragHandler(),
51+
_Header(
52+
title: widget.title,
53+
onDone: (context) => context.pop(newFieldId),
5154
),
52-
),
53-
),
54-
],
55+
SingleChildScrollView(
56+
controller: scrollController,
57+
child: ListView.builder(
58+
shrinkWrap: true,
59+
itemCount: widget.fields.length,
60+
itemBuilder: (context, index) => _FieldButton(
61+
field: widget.fields[index],
62+
showTopBorder: index == 0,
63+
isSelected: widget.fields[index].id == newFieldId,
64+
onSelect: (fieldId) => setState(() => newFieldId = fieldId),
65+
),
66+
),
67+
),
68+
],
69+
);
70+
},
5571
);
5672
}
5773
}
5874

75+
/// Same header as the one in showMobileBottomSheet, but allows popping the
76+
/// sheet with a value.
5977
class _Header extends StatelessWidget {
60-
const _Header({required this.newFieldId});
78+
const _Header({
79+
required this.title,
80+
required this.onDone,
81+
});
6182

62-
final String? newFieldId;
83+
final String title;
84+
final void Function(BuildContext context) onDone;
6385

6486
@override
6587
Widget build(BuildContext context) {
66-
return Stack(
67-
alignment: Alignment.center,
68-
children: [
69-
Row(
70-
mainAxisAlignment: MainAxisAlignment.spaceBetween,
88+
return Padding(
89+
padding: const EdgeInsets.only(bottom: 4.0),
90+
child: SizedBox(
91+
height: 44.0,
92+
child: Stack(
7193
children: [
72-
SizedBox.square(
73-
dimension: 36,
74-
child: IconButton(
75-
highlightColor: Colors.transparent,
76-
splashColor: Colors.transparent,
77-
padding: EdgeInsets.zero,
78-
onPressed: () => context.pop(),
79-
icon: const FlowySvg(
80-
FlowySvgs.arrow_left_s,
81-
size: Size.square(20),
82-
),
94+
const Align(
95+
alignment: Alignment.centerLeft,
96+
child: AppBarBackButton(),
97+
),
98+
Align(
99+
child: FlowyText.medium(
100+
title,
101+
fontSize: 16.0,
83102
),
84103
),
85-
Padding(
86-
padding: const EdgeInsets.fromLTRB(8, 4, 8, 8),
87-
child: TextButton(
88-
style: TextButton.styleFrom(
89-
padding: const EdgeInsets.symmetric(
90-
horizontal: 12,
91-
vertical: 5,
92-
),
93-
shape: RoundedRectangleBorder(
94-
borderRadius: BorderRadius.circular(10),
95-
),
96-
elevation: 0,
97-
visualDensity: VisualDensity.compact,
98-
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
99-
enableFeedback: true,
100-
backgroundColor: Theme.of(context).primaryColor,
101-
),
102-
onPressed: () => context.pop(newFieldId),
103-
child: FlowyText.medium(
104-
LocaleKeys.button_done.tr(),
105-
fontSize: 16,
106-
color: Theme.of(context).colorScheme.onPrimary,
107-
overflow: TextOverflow.ellipsis,
108-
),
104+
Align(
105+
alignment: Alignment.centerRight,
106+
child: AppBarDoneButton(
107+
onTap: () => onDone(context),
109108
),
110109
),
111110
],
112111
),
113-
Center(
114-
child: FlowyText.medium(
115-
LocaleKeys.calendar_settings_changeLayoutDateField.tr(),
116-
fontSize: 16,
117-
),
118-
),
119-
],
112+
),
120113
);
121114
}
122115
}

0 commit comments

Comments
 (0)