mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-09-26 17:03:05 +00:00
refactor: replace FlowyOverlay with AppFlowyPopover in select option
This commit is contained in:
parent
3a1148d11a
commit
6c27b5455e
@ -2,6 +2,8 @@ import 'package:app_flowy/plugins/board/application/card/board_select_option_cel
|
|||||||
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
|
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
|
||||||
import 'package:app_flowy/plugins/grid/presentation/widgets/cell/select_option_cell/extension.dart';
|
import 'package:app_flowy/plugins/grid/presentation/widgets/cell/select_option_cell/extension.dart';
|
||||||
import 'package:app_flowy/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart';
|
import 'package:app_flowy/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart';
|
||||||
|
import 'package:appflowy_popover/popover.dart';
|
||||||
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
@ -26,9 +28,11 @@ class BoardSelectOptionCell extends StatefulWidget with EditableCell {
|
|||||||
|
|
||||||
class _BoardSelectOptionCellState extends State<BoardSelectOptionCell> {
|
class _BoardSelectOptionCellState extends State<BoardSelectOptionCell> {
|
||||||
late BoardSelectOptionCellBloc _cellBloc;
|
late BoardSelectOptionCellBloc _cellBloc;
|
||||||
|
late PopoverController _popover;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
_popover = PopoverController();
|
||||||
final cellController =
|
final cellController =
|
||||||
widget.cellControllerBuilder.build() as GridSelectOptionCellController;
|
widget.cellControllerBuilder.build() as GridSelectOptionCellController;
|
||||||
_cellBloc = BoardSelectOptionCellBloc(cellController: cellController)
|
_cellBloc = BoardSelectOptionCellBloc(cellController: cellController)
|
||||||
@ -43,29 +47,20 @@ class _BoardSelectOptionCellState extends State<BoardSelectOptionCell> {
|
|||||||
child: BlocBuilder<BoardSelectOptionCellBloc, BoardSelectOptionCellState>(
|
child: BlocBuilder<BoardSelectOptionCellBloc, BoardSelectOptionCellState>(
|
||||||
buildWhen: (previous, current) {
|
buildWhen: (previous, current) {
|
||||||
return previous.selectedOptions != current.selectedOptions;
|
return previous.selectedOptions != current.selectedOptions;
|
||||||
},
|
}, builder: (context, state) {
|
||||||
builder: (context, state) {
|
// Returns SizedBox if the content of the cell is empty
|
||||||
if (state.selectedOptions
|
if (_isEmpty(state)) return const SizedBox();
|
||||||
.where((element) => element.id == widget.groupId)
|
|
||||||
.isNotEmpty ||
|
final children = state.selectedOptions.map(
|
||||||
state.selectedOptions.isEmpty) {
|
(option) {
|
||||||
return const SizedBox();
|
final tag = SelectOptionTag.fromOption(
|
||||||
} else {
|
|
||||||
final children = state.selectedOptions
|
|
||||||
.map(
|
|
||||||
(option) => SelectOptionTag.fromOption(
|
|
||||||
context: context,
|
context: context,
|
||||||
option: option,
|
option: option,
|
||||||
onSelected: () {
|
onSelected: () => _popover.show(),
|
||||||
SelectOptionCellEditor.show(
|
|
||||||
context: context,
|
|
||||||
cellController: widget.cellControllerBuilder.build()
|
|
||||||
as GridSelectOptionCellController,
|
|
||||||
);
|
);
|
||||||
|
return _wrapPopover(tag);
|
||||||
},
|
},
|
||||||
),
|
).toList();
|
||||||
)
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
return IntrinsicHeight(
|
return IntrinsicHeight(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@ -75,9 +70,35 @@ class _BoardSelectOptionCellState extends State<BoardSelectOptionCell> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _isEmpty(BoardSelectOptionCellState state) {
|
||||||
|
// The cell should hide if the option id is equal to the groupId.
|
||||||
|
final isInGroup = state.selectedOptions
|
||||||
|
.where((element) => element.id == widget.groupId)
|
||||||
|
.isNotEmpty;
|
||||||
|
return isInGroup || state.selectedOptions.isEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _wrapPopover(Widget child) {
|
||||||
|
final constraints = BoxConstraints.loose(Size(
|
||||||
|
SelectOptionCellEditor.editorPanelWidth,
|
||||||
|
300,
|
||||||
|
));
|
||||||
|
return AppFlowyStylePopover(
|
||||||
|
controller: _popover,
|
||||||
|
constraints: constraints,
|
||||||
|
direction: PopoverDirection.bottomWithLeftAligned,
|
||||||
|
popupBuilder: (BuildContext context) {
|
||||||
|
return SelectOptionCellEditor(
|
||||||
|
cellController: widget.cellControllerBuilder.build()
|
||||||
|
as GridSelectOptionCellController,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
onClose: () {},
|
||||||
|
child: child,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,67 +164,65 @@ class _SelectOptionWrapState extends State<SelectOptionWrap> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = context.watch<AppTheme>();
|
final theme = context.watch<AppTheme>();
|
||||||
final Widget child;
|
Widget child = _buildOptions(theme, context);
|
||||||
if (widget.selectOptions.isEmpty && widget.cellStyle != null) {
|
|
||||||
child = Align(
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: FlowyText.medium(
|
|
||||||
widget.cellStyle!.placeholder,
|
|
||||||
fontSize: 14,
|
|
||||||
color: theme.shader3,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
child = Align(
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Wrap(
|
|
||||||
spacing: 4,
|
|
||||||
runSpacing: 2,
|
|
||||||
children: widget.selectOptions
|
|
||||||
.map((option) => SelectOptionTag.fromOption(
|
|
||||||
context: context,
|
|
||||||
option: option,
|
|
||||||
))
|
|
||||||
.toList(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Stack(
|
return Stack(
|
||||||
alignment: AlignmentDirectional.center,
|
alignment: AlignmentDirectional.center,
|
||||||
fit: StackFit.expand,
|
fit: StackFit.expand,
|
||||||
children: [
|
children: [
|
||||||
AppFlowyStylePopover(
|
_wrapPopover(child),
|
||||||
controller: _popover,
|
InkWell(onTap: () => _popover.show()),
|
||||||
constraints: BoxConstraints.loose(
|
|
||||||
Size(SelectOptionCellEditor.editorPanelWidth, 300)),
|
|
||||||
offset: const Offset(0, 20),
|
|
||||||
direction: PopoverDirection.bottomWithLeftAligned,
|
|
||||||
// triggerActions: PopoverTriggerActionFlags.c,
|
|
||||||
popupBuilder: (BuildContext context) {
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
|
||||||
widget.onFocus?.call(true);
|
|
||||||
});
|
|
||||||
return SizedBox(
|
|
||||||
width: SelectOptionCellEditor.editorPanelWidth,
|
|
||||||
child: SelectOptionCellEditor(
|
|
||||||
cellController: widget.cellControllerBuilder.build()
|
|
||||||
as GridSelectOptionCellController,
|
|
||||||
onDismissed: () {
|
|
||||||
widget.onFocus?.call(false);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onClose: () {
|
|
||||||
widget.onFocus?.call(false);
|
|
||||||
},
|
|
||||||
child: child,
|
|
||||||
),
|
|
||||||
InkWell(onTap: () {
|
|
||||||
_popover.show();
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _wrapPopover(Widget child) {
|
||||||
|
final constraints = BoxConstraints.loose(Size(
|
||||||
|
SelectOptionCellEditor.editorPanelWidth,
|
||||||
|
300,
|
||||||
|
));
|
||||||
|
return AppFlowyStylePopover(
|
||||||
|
controller: _popover,
|
||||||
|
constraints: constraints,
|
||||||
|
direction: PopoverDirection.bottomWithLeftAligned,
|
||||||
|
popupBuilder: (BuildContext context) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
widget.onFocus?.call(true);
|
||||||
|
});
|
||||||
|
return SelectOptionCellEditor(
|
||||||
|
cellController: widget.cellControllerBuilder.build()
|
||||||
|
as GridSelectOptionCellController,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onClose: () => widget.onFocus?.call(false),
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildOptions(AppTheme theme, BuildContext context) {
|
||||||
|
final Widget child;
|
||||||
|
if (widget.selectOptions.isEmpty && widget.cellStyle != null) {
|
||||||
|
child = FlowyText.medium(
|
||||||
|
widget.cellStyle!.placeholder,
|
||||||
|
fontSize: 14,
|
||||||
|
color: theme.shader3,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
final children = widget.selectOptions.map(
|
||||||
|
(option) {
|
||||||
|
return SelectOptionTag.fromOption(
|
||||||
|
context: context,
|
||||||
|
option: option,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
).toList();
|
||||||
|
|
||||||
|
child = Wrap(
|
||||||
|
spacing: 4,
|
||||||
|
runSpacing: 2,
|
||||||
|
children: children,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Align(alignment: Alignment.centerLeft, child: child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,17 +25,13 @@ import 'text_field.dart';
|
|||||||
|
|
||||||
const double _editorPanelWidth = 300;
|
const double _editorPanelWidth = 300;
|
||||||
|
|
||||||
class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate {
|
class SelectOptionCellEditor extends StatelessWidget {
|
||||||
final GridSelectOptionCellController cellController;
|
final GridSelectOptionCellController cellController;
|
||||||
final VoidCallback? onDismissed;
|
|
||||||
|
|
||||||
static double editorPanelWidth = 300;
|
static double editorPanelWidth = 300;
|
||||||
|
|
||||||
const SelectOptionCellEditor({
|
const SelectOptionCellEditor({required this.cellController, Key? key})
|
||||||
required this.cellController,
|
: super(key: key);
|
||||||
this.onDismissed,
|
|
||||||
Key? key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -60,44 +56,6 @@ class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show({
|
|
||||||
required BuildContext context,
|
|
||||||
required GridSelectOptionCellController cellController,
|
|
||||||
VoidCallback? onDismissed,
|
|
||||||
}) {
|
|
||||||
SelectOptionCellEditor.remove(context);
|
|
||||||
final editor = SelectOptionCellEditor(
|
|
||||||
cellController: cellController,
|
|
||||||
onDismissed: onDismissed,
|
|
||||||
);
|
|
||||||
|
|
||||||
//
|
|
||||||
FlowyOverlay.of(context).insertWithAnchor(
|
|
||||||
widget: OverlayContainer(
|
|
||||||
constraints: BoxConstraints.loose(const Size(_editorPanelWidth, 300)),
|
|
||||||
child: SizedBox(width: _editorPanelWidth, child: editor),
|
|
||||||
),
|
|
||||||
identifier: SelectOptionCellEditor.identifier(),
|
|
||||||
anchorContext: context,
|
|
||||||
anchorDirection: AnchorDirection.bottomWithCenterAligned,
|
|
||||||
delegate: editor,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void remove(BuildContext context) {
|
|
||||||
FlowyOverlay.of(context).remove(identifier());
|
|
||||||
}
|
|
||||||
|
|
||||||
static String identifier() {
|
|
||||||
return (SelectOptionCellEditor).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool asBarrier() => true;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didRemove() => onDismissed?.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _OptionList extends StatelessWidget {
|
class _OptionList extends StatelessWidget {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user