mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: select option mouse-click event conflict (#4003)
This commit is contained in:
parent
c475a5d960
commit
29a6eab1ce
@ -1,6 +1,8 @@
|
|||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/plugins/database_view/grid/application/filter/select_option_filter_list_bloc.dart';
|
import 'package:appflowy/plugins/database_view/grid/application/filter/select_option_filter_list_bloc.dart';
|
||||||
import 'package:appflowy/plugins/database_view/grid/presentation/layout/sizes.dart';
|
import 'package:appflowy/plugins/database_view/grid/presentation/layout/sizes.dart';
|
||||||
|
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/filter/filter_info.dart';
|
||||||
|
import 'package:appflowy/plugins/database_view/widgets/row/cells/select_option_cell/extension.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database2/select_option.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database2/select_option.pb.dart';
|
||||||
|
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
@ -8,8 +10,6 @@ import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import '../../../../../../widgets/row/cells/select_option_cell/extension.dart';
|
|
||||||
import '../../filter_info.dart';
|
|
||||||
import 'select_option_loader.dart';
|
import 'select_option_loader.dart';
|
||||||
|
|
||||||
class SelectOptionFilterList extends StatelessWidget {
|
class SelectOptionFilterList extends StatelessWidget {
|
||||||
@ -86,8 +86,8 @@ class SelectOptionFilterCell extends StatefulWidget {
|
|||||||
const SelectOptionFilterCell({
|
const SelectOptionFilterCell({
|
||||||
required this.option,
|
required this.option,
|
||||||
required this.isSelected,
|
required this.isSelected,
|
||||||
Key? key,
|
super.key,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<SelectOptionFilterCell> createState() => _SelectOptionFilterCellState();
|
State<SelectOptionFilterCell> createState() => _SelectOptionFilterCellState();
|
||||||
@ -100,15 +100,15 @@ class _SelectOptionFilterCellState extends State<SelectOptionFilterCell> {
|
|||||||
height: GridSize.popoverItemHeight,
|
height: GridSize.popoverItemHeight,
|
||||||
child: SelectOptionTagCell(
|
child: SelectOptionTagCell(
|
||||||
option: widget.option,
|
option: widget.option,
|
||||||
onSelected: (option) {
|
onSelected: () {
|
||||||
if (widget.isSelected) {
|
if (widget.isSelected) {
|
||||||
context
|
context
|
||||||
.read<SelectOptionFilterListBloc>()
|
.read<SelectOptionFilterListBloc>()
|
||||||
.add(SelectOptionFilterListEvent.unselectOption(option));
|
.add(SelectOptionFilterListEvent.unselectOption(widget.option));
|
||||||
} else {
|
} else {
|
||||||
context
|
context
|
||||||
.read<SelectOptionFilterListBloc>()
|
.read<SelectOptionFilterListBloc>()
|
||||||
.add(SelectOptionFilterListEvent.selectOption(option));
|
.add(SelectOptionFilterListEvent.selectOption(widget.option));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
|
@ -31,10 +31,10 @@ class MultiSelectTypeOptionWidget extends TypeOptionWidget {
|
|||||||
final PopoverMutex? popoverMutex;
|
final PopoverMutex? popoverMutex;
|
||||||
|
|
||||||
const MultiSelectTypeOptionWidget({
|
const MultiSelectTypeOptionWidget({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.selectOptionAction,
|
required this.selectOptionAction,
|
||||||
this.popoverMutex,
|
this.popoverMutex,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -21,12 +21,12 @@ class SelectOptionTypeOptionWidget extends StatelessWidget {
|
|||||||
final PopoverMutex? popoverMutex;
|
final PopoverMutex? popoverMutex;
|
||||||
|
|
||||||
const SelectOptionTypeOptionWidget({
|
const SelectOptionTypeOptionWidget({
|
||||||
|
super.key,
|
||||||
required this.options,
|
required this.options,
|
||||||
required this.beginEdit,
|
required this.beginEdit,
|
||||||
required this.typeOptionAction,
|
required this.typeOptionAction,
|
||||||
this.popoverMutex,
|
this.popoverMutex,
|
||||||
Key? key,
|
});
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -96,8 +96,7 @@ class _OptionList extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final cells = state.options.map((option) {
|
final cells = state.options.map((option) {
|
||||||
return _makeOptionCell(
|
return _OptionCell(
|
||||||
context: context,
|
|
||||||
option: option,
|
option: option,
|
||||||
popoverMutex: popoverMutex,
|
popoverMutex: popoverMutex,
|
||||||
);
|
);
|
||||||
@ -116,17 +115,6 @@ class _OptionList extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_OptionCell _makeOptionCell({
|
|
||||||
required BuildContext context,
|
|
||||||
required SelectOptionPB option,
|
|
||||||
PopoverMutex? popoverMutex,
|
|
||||||
}) {
|
|
||||||
return _OptionCell(
|
|
||||||
option: option,
|
|
||||||
popoverMutex: popoverMutex,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _OptionCell extends StatefulWidget {
|
class _OptionCell extends StatefulWidget {
|
||||||
@ -154,13 +142,13 @@ class _OptionCellState extends State<_OptionCell> {
|
|||||||
height: 28,
|
height: 28,
|
||||||
child: SelectOptionTagCell(
|
child: SelectOptionTagCell(
|
||||||
option: widget.option,
|
option: widget.option,
|
||||||
onSelected: (SelectOptionPB pb) {
|
onSelected: () => _popoverController.show(),
|
||||||
_popoverController.show();
|
|
||||||
},
|
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
FlowyIconButton(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 6.0),
|
onPressed: () => _popoverController.show(),
|
||||||
child: FlowySvg(
|
iconPadding: const EdgeInsets.symmetric(horizontal: 6.0),
|
||||||
|
hoverColor: Colors.transparent,
|
||||||
|
icon: FlowySvg(
|
||||||
FlowySvgs.details_s,
|
FlowySvgs.details_s,
|
||||||
color: Theme.of(context).iconTheme.color,
|
color: Theme.of(context).iconTheme.color,
|
||||||
),
|
),
|
||||||
@ -228,10 +216,11 @@ class _AddOptionButton extends StatelessWidget {
|
|||||||
|
|
||||||
class CreateOptionTextField extends StatefulWidget {
|
class CreateOptionTextField extends StatefulWidget {
|
||||||
final PopoverMutex? popoverMutex;
|
final PopoverMutex? popoverMutex;
|
||||||
|
|
||||||
const CreateOptionTextField({
|
const CreateOptionTextField({
|
||||||
Key? key,
|
super.key,
|
||||||
this.popoverMutex,
|
this.popoverMutex,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<CreateOptionTextField> createState() => _CreateOptionTextFieldState();
|
State<CreateOptionTextField> createState() => _CreateOptionTextFieldState();
|
||||||
|
@ -30,10 +30,10 @@ class SingleSelectTypeOptionWidget extends TypeOptionWidget {
|
|||||||
final PopoverMutex? popoverMutex;
|
final PopoverMutex? popoverMutex;
|
||||||
|
|
||||||
const SingleSelectTypeOptionWidget({
|
const SingleSelectTypeOptionWidget({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.selectOptionAction,
|
required this.selectOptionAction,
|
||||||
this.popoverMutex,
|
this.popoverMutex,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -64,26 +64,23 @@ extension SelectOptionColorExtension on SelectOptionColorPB {
|
|||||||
class SelectOptionTag extends StatelessWidget {
|
class SelectOptionTag extends StatelessWidget {
|
||||||
final String name;
|
final String name;
|
||||||
final Color color;
|
final Color color;
|
||||||
final VoidCallback? onSelected;
|
|
||||||
final void Function(String)? onRemove;
|
final void Function(String)? onRemove;
|
||||||
|
|
||||||
const SelectOptionTag({
|
const SelectOptionTag({
|
||||||
required this.name,
|
required this.name,
|
||||||
required this.color,
|
required this.color,
|
||||||
this.onSelected,
|
|
||||||
this.onRemove,
|
this.onRemove,
|
||||||
Key? key,
|
super.key,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
factory SelectOptionTag.fromOption({
|
factory SelectOptionTag.fromOption({
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
required SelectOptionPB option,
|
required SelectOptionPB option,
|
||||||
VoidCallback? onSelected,
|
|
||||||
Function(String)? onRemove,
|
Function(String)? onRemove,
|
||||||
}) {
|
}) {
|
||||||
return SelectOptionTag(
|
return SelectOptionTag(
|
||||||
name: option.name,
|
name: option.name,
|
||||||
color: option.color.toColor(context),
|
color: option.color.toColor(context),
|
||||||
onSelected: onSelected,
|
|
||||||
onRemove: onRemove,
|
onRemove: onRemove,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -119,9 +116,7 @@ class SelectOptionTag extends StatelessWidget {
|
|||||||
width: 18.0,
|
width: 18.0,
|
||||||
onPressed: () => onRemove?.call(name),
|
onPressed: () => onRemove?.call(name),
|
||||||
hoverColor: Colors.transparent,
|
hoverColor: Colors.transparent,
|
||||||
icon: const FlowySvg(
|
icon: const FlowySvg(FlowySvgs.close_s),
|
||||||
FlowySvgs.close_s,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -131,9 +126,6 @@ class SelectOptionTag extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SelectOptionTagCell extends StatelessWidget {
|
class SelectOptionTagCell extends StatelessWidget {
|
||||||
final List<Widget> children;
|
|
||||||
final void Function(SelectOptionPB) onSelected;
|
|
||||||
final SelectOptionPB option;
|
|
||||||
const SelectOptionTagCell({
|
const SelectOptionTagCell({
|
||||||
super.key,
|
super.key,
|
||||||
required this.option,
|
required this.option,
|
||||||
@ -141,25 +133,31 @@ class SelectOptionTagCell extends StatelessWidget {
|
|||||||
this.children = const [],
|
this.children = const [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
final SelectOptionPB option;
|
||||||
|
final VoidCallback onSelected;
|
||||||
|
final List<Widget> children;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FlowyHover(
|
return FlowyHover(
|
||||||
style: HoverStyle(
|
style: HoverStyle(
|
||||||
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||||
),
|
),
|
||||||
child: InkWell(
|
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
|
onTap: onSelected,
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: AlignmentDirectional.centerStart,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(5.0),
|
padding: const EdgeInsets.all(5.0),
|
||||||
child: SelectOptionTag.fromOption(
|
child: SelectOptionTag.fromOption(
|
||||||
context: context,
|
context: context,
|
||||||
option: option,
|
option: option,
|
||||||
onSelected: () => onSelected(option),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -167,9 +165,6 @@ class SelectOptionTagCell extends StatelessWidget {
|
|||||||
...children,
|
...children,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
// TODO(richard): find alternative solution to onTapDown
|
|
||||||
onTapDown: (_) => onSelected(option),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,8 +246,13 @@ class _CreateOptionCell extends StatelessWidget {
|
|||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: GridSize.popoverItemHeight,
|
height: 28,
|
||||||
child: Row(
|
child: FlowyButton(
|
||||||
|
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||||
|
onTap: () => context
|
||||||
|
.read<SelectOptionCellEditorBloc>()
|
||||||
|
.add(SelectOptionEditorEvent.newOption(name)),
|
||||||
|
text: Row(
|
||||||
children: [
|
children: [
|
||||||
FlowyText.medium(
|
FlowyText.medium(
|
||||||
LocaleKeys.grid_selectOption_create.tr(),
|
LocaleKeys.grid_selectOption_create.tr(),
|
||||||
@ -259,16 +264,14 @@ class _CreateOptionCell extends StatelessWidget {
|
|||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: SelectOptionTag(
|
child: SelectOptionTag(
|
||||||
name: name,
|
name: name,
|
||||||
color: AFThemeExtension.of(context).greyHover,
|
color: Theme.of(context).colorScheme.surfaceVariant,
|
||||||
onSelected: () => context
|
|
||||||
.read<SelectOptionCellEditorBloc>()
|
|
||||||
.add(SelectOptionEditorEvent.newOption(name)),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -304,27 +307,20 @@ class _SelectOptionCellState extends State<_SelectOptionCell> {
|
|||||||
height: 28,
|
height: 28,
|
||||||
child: SelectOptionTagCell(
|
child: SelectOptionTagCell(
|
||||||
option: widget.option,
|
option: widget.option,
|
||||||
onSelected: (option) {
|
onSelected: _onTap,
|
||||||
if (widget.isSelected) {
|
|
||||||
context
|
|
||||||
.read<SelectOptionCellEditorBloc>()
|
|
||||||
.add(SelectOptionEditorEvent.unSelectOption(option.id));
|
|
||||||
} else {
|
|
||||||
context
|
|
||||||
.read<SelectOptionCellEditorBloc>()
|
|
||||||
.add(SelectOptionEditorEvent.selectOption(option.id));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
children: [
|
children: [
|
||||||
if (widget.isSelected)
|
if (widget.isSelected)
|
||||||
Padding(
|
FlowyIconButton(
|
||||||
padding: const EdgeInsets.only(left: 6),
|
width: 20,
|
||||||
child: FlowySvg(
|
hoverColor: Colors.transparent,
|
||||||
|
onPressed: _onTap,
|
||||||
|
icon: FlowySvg(
|
||||||
FlowySvgs.check_s,
|
FlowySvgs.check_s,
|
||||||
color: Theme.of(context).iconTheme.color,
|
color: Theme.of(context).iconTheme.color,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
FlowyIconButton(
|
FlowyIconButton(
|
||||||
|
width: 30,
|
||||||
onPressed: () => _popoverController.show(),
|
onPressed: () => _popoverController.show(),
|
||||||
iconPadding: const EdgeInsets.symmetric(horizontal: 6.0),
|
iconPadding: const EdgeInsets.symmetric(horizontal: 6.0),
|
||||||
hoverColor: Colors.transparent,
|
hoverColor: Colors.transparent,
|
||||||
@ -368,4 +364,17 @@ class _SelectOptionCellState extends State<_SelectOptionCell> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onTap() {
|
||||||
|
widget.popoverMutex.close();
|
||||||
|
if (widget.isSelected) {
|
||||||
|
context
|
||||||
|
.read<SelectOptionCellEditorBloc>()
|
||||||
|
.add(SelectOptionEditorEvent.unSelectOption(widget.option.id));
|
||||||
|
} else {
|
||||||
|
context
|
||||||
|
.read<SelectOptionCellEditorBloc>()
|
||||||
|
.add(SelectOptionEditorEvent.selectOption(widget.option.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user