Skip to content

Commit 6c27b54

Browse files
committed
refactor: replace FlowyOverlay with AppFlowyPopover in select option
1 parent 3a1148d commit 6c27b54

File tree

3 files changed

+112
-135
lines changed

3 files changed

+112
-135
lines changed

frontend/app_flowy/lib/plugins/board/presentation/card/board_select_option_cell.dart

Lines changed: 56 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import 'package:app_flowy/plugins/board/application/card/board_select_option_cel
22
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
33
import 'package:app_flowy/plugins/grid/presentation/widgets/cell/select_option_cell/extension.dart';
44
import 'package:app_flowy/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart';
5+
import 'package:appflowy_popover/popover.dart';
6+
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
57
import 'package:flutter/material.dart';
68
import 'package:flutter_bloc/flutter_bloc.dart';
79

@@ -26,9 +28,11 @@ class BoardSelectOptionCell extends StatefulWidget with EditableCell {
2628

2729
class _BoardSelectOptionCellState extends State<BoardSelectOptionCell> {
2830
late BoardSelectOptionCellBloc _cellBloc;
31+
late PopoverController _popover;
2932

3033
@override
3134
void initState() {
35+
_popover = PopoverController();
3236
final cellController =
3337
widget.cellControllerBuilder.build() as GridSelectOptionCellController;
3438
_cellBloc = BoardSelectOptionCellBloc(cellController: cellController)
@@ -41,43 +45,60 @@ class _BoardSelectOptionCellState extends State<BoardSelectOptionCell> {
4145
return BlocProvider.value(
4246
value: _cellBloc,
4347
child: BlocBuilder<BoardSelectOptionCellBloc, BoardSelectOptionCellState>(
44-
buildWhen: (previous, current) {
45-
return previous.selectedOptions != current.selectedOptions;
46-
},
47-
builder: (context, state) {
48-
if (state.selectedOptions
49-
.where((element) => element.id == widget.groupId)
50-
.isNotEmpty ||
51-
state.selectedOptions.isEmpty) {
52-
return const SizedBox();
53-
} else {
54-
final children = state.selectedOptions
55-
.map(
56-
(option) => SelectOptionTag.fromOption(
57-
context: context,
58-
option: option,
59-
onSelected: () {
60-
SelectOptionCellEditor.show(
61-
context: context,
62-
cellController: widget.cellControllerBuilder.build()
63-
as GridSelectOptionCellController,
64-
);
65-
},
66-
),
67-
)
68-
.toList();
48+
buildWhen: (previous, current) {
49+
return previous.selectedOptions != current.selectedOptions;
50+
}, builder: (context, state) {
51+
// Returns SizedBox if the content of the cell is empty
52+
if (_isEmpty(state)) return const SizedBox();
6953

70-
return IntrinsicHeight(
71-
child: Padding(
72-
padding: const EdgeInsets.symmetric(vertical: 6),
73-
child: SizedBox.expand(
74-
child: Wrap(spacing: 4, runSpacing: 2, children: children),
75-
),
76-
),
54+
final children = state.selectedOptions.map(
55+
(option) {
56+
final tag = SelectOptionTag.fromOption(
57+
context: context,
58+
option: option,
59+
onSelected: () => _popover.show(),
7760
);
78-
}
79-
},
80-
),
61+
return _wrapPopover(tag);
62+
},
63+
).toList();
64+
65+
return IntrinsicHeight(
66+
child: Padding(
67+
padding: const EdgeInsets.symmetric(vertical: 6),
68+
child: SizedBox.expand(
69+
child: Wrap(spacing: 4, runSpacing: 2, children: children),
70+
),
71+
),
72+
);
73+
}),
74+
);
75+
}
76+
77+
bool _isEmpty(BoardSelectOptionCellState state) {
78+
// The cell should hide if the option id is equal to the groupId.
79+
final isInGroup = state.selectedOptions
80+
.where((element) => element.id == widget.groupId)
81+
.isNotEmpty;
82+
return isInGroup || state.selectedOptions.isEmpty;
83+
}
84+
85+
Widget _wrapPopover(Widget child) {
86+
final constraints = BoxConstraints.loose(Size(
87+
SelectOptionCellEditor.editorPanelWidth,
88+
300,
89+
));
90+
return AppFlowyStylePopover(
91+
controller: _popover,
92+
constraints: constraints,
93+
direction: PopoverDirection.bottomWithLeftAligned,
94+
popupBuilder: (BuildContext context) {
95+
return SelectOptionCellEditor(
96+
cellController: widget.cellControllerBuilder.build()
97+
as GridSelectOptionCellController,
98+
);
99+
},
100+
onClose: () {},
101+
child: child,
81102
);
82103
}
83104

frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart

Lines changed: 53 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -164,67 +164,65 @@ class _SelectOptionWrapState extends State<SelectOptionWrap> {
164164
@override
165165
Widget build(BuildContext context) {
166166
final theme = context.watch<AppTheme>();
167-
final Widget child;
168-
if (widget.selectOptions.isEmpty && widget.cellStyle != null) {
169-
child = Align(
170-
alignment: Alignment.centerLeft,
171-
child: FlowyText.medium(
172-
widget.cellStyle!.placeholder,
173-
fontSize: 14,
174-
color: theme.shader3,
175-
),
176-
);
177-
} else {
178-
child = Align(
179-
alignment: Alignment.centerLeft,
180-
child: Wrap(
181-
spacing: 4,
182-
runSpacing: 2,
183-
children: widget.selectOptions
184-
.map((option) => SelectOptionTag.fromOption(
185-
context: context,
186-
option: option,
187-
))
188-
.toList(),
189-
),
190-
);
191-
}
167+
Widget child = _buildOptions(theme, context);
192168

193169
return Stack(
194170
alignment: AlignmentDirectional.center,
195171
fit: StackFit.expand,
196172
children: [
197-
AppFlowyStylePopover(
198-
controller: _popover,
199-
constraints: BoxConstraints.loose(
200-
Size(SelectOptionCellEditor.editorPanelWidth, 300)),
201-
offset: const Offset(0, 20),
202-
direction: PopoverDirection.bottomWithLeftAligned,
203-
// triggerActions: PopoverTriggerActionFlags.c,
204-
popupBuilder: (BuildContext context) {
205-
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
206-
widget.onFocus?.call(true);
207-
});
208-
return SizedBox(
209-
width: SelectOptionCellEditor.editorPanelWidth,
210-
child: SelectOptionCellEditor(
211-
cellController: widget.cellControllerBuilder.build()
212-
as GridSelectOptionCellController,
213-
onDismissed: () {
214-
widget.onFocus?.call(false);
215-
},
216-
),
217-
);
218-
},
219-
onClose: () {
220-
widget.onFocus?.call(false);
221-
},
222-
child: child,
223-
),
224-
InkWell(onTap: () {
225-
_popover.show();
226-
}),
173+
_wrapPopover(child),
174+
InkWell(onTap: () => _popover.show()),
227175
],
228176
);
229177
}
178+
179+
Widget _wrapPopover(Widget child) {
180+
final constraints = BoxConstraints.loose(Size(
181+
SelectOptionCellEditor.editorPanelWidth,
182+
300,
183+
));
184+
return AppFlowyStylePopover(
185+
controller: _popover,
186+
constraints: constraints,
187+
direction: PopoverDirection.bottomWithLeftAligned,
188+
popupBuilder: (BuildContext context) {
189+
WidgetsBinding.instance.addPostFrameCallback((_) {
190+
widget.onFocus?.call(true);
191+
});
192+
return SelectOptionCellEditor(
193+
cellController: widget.cellControllerBuilder.build()
194+
as GridSelectOptionCellController,
195+
);
196+
},
197+
onClose: () => widget.onFocus?.call(false),
198+
child: child,
199+
);
200+
}
201+
202+
Widget _buildOptions(AppTheme theme, BuildContext context) {
203+
final Widget child;
204+
if (widget.selectOptions.isEmpty && widget.cellStyle != null) {
205+
child = FlowyText.medium(
206+
widget.cellStyle!.placeholder,
207+
fontSize: 14,
208+
color: theme.shader3,
209+
);
210+
} else {
211+
final children = widget.selectOptions.map(
212+
(option) {
213+
return SelectOptionTag.fromOption(
214+
context: context,
215+
option: option,
216+
);
217+
},
218+
).toList();
219+
220+
child = Wrap(
221+
spacing: 4,
222+
runSpacing: 2,
223+
children: children,
224+
);
225+
}
226+
return Align(alignment: Alignment.centerLeft, child: child);
227+
}
230228
}

frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart

Lines changed: 3 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,13 @@ import 'text_field.dart';
2525

2626
const double _editorPanelWidth = 300;
2727

28-
class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate {
28+
class SelectOptionCellEditor extends StatelessWidget {
2929
final GridSelectOptionCellController cellController;
30-
final VoidCallback? onDismissed;
3130

3231
static double editorPanelWidth = 300;
3332

34-
const SelectOptionCellEditor({
35-
required this.cellController,
36-
this.onDismissed,
37-
Key? key,
38-
}) : super(key: key);
33+
const SelectOptionCellEditor({required this.cellController, Key? key})
34+
: super(key: key);
3935

4036
@override
4137
Widget build(BuildContext context) {
@@ -60,44 +56,6 @@ class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate {
6056
),
6157
);
6258
}
63-
64-
static void show({
65-
required BuildContext context,
66-
required GridSelectOptionCellController cellController,
67-
VoidCallback? onDismissed,
68-
}) {
69-
SelectOptionCellEditor.remove(context);
70-
final editor = SelectOptionCellEditor(
71-
cellController: cellController,
72-
onDismissed: onDismissed,
73-
);
74-
75-
//
76-
FlowyOverlay.of(context).insertWithAnchor(
77-
widget: OverlayContainer(
78-
constraints: BoxConstraints.loose(const Size(_editorPanelWidth, 300)),
79-
child: SizedBox(width: _editorPanelWidth, child: editor),
80-
),
81-
identifier: SelectOptionCellEditor.identifier(),
82-
anchorContext: context,
83-
anchorDirection: AnchorDirection.bottomWithCenterAligned,
84-
delegate: editor,
85-
);
86-
}
87-
88-
static void remove(BuildContext context) {
89-
FlowyOverlay.of(context).remove(identifier());
90-
}
91-
92-
static String identifier() {
93-
return (SelectOptionCellEditor).toString();
94-
}
95-
96-
@override
97-
bool asBarrier() => true;
98-
99-
@override
100-
void didRemove() => onDismissed?.call();
10159
}
10260

10361
class _OptionList extends StatelessWidget {

0 commit comments

Comments
 (0)