mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: add mutex to property list
This commit is contained in:
parent
4c31c0dcf0
commit
8229371f63
@ -1,6 +1,7 @@
|
|||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
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/application/cell/select_option_editor_bloc.dart';
|
import 'package:app_flowy/plugins/grid/application/cell/select_option_editor_bloc.dart';
|
||||||
|
import 'package:appflowy_popover/popover.dart';
|
||||||
|
|
||||||
import 'package:flowy_infra/image.dart';
|
import 'package:flowy_infra/image.dart';
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
@ -228,76 +229,82 @@ class _CreateOptionCell extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SelectOptionCell extends StatelessWidget {
|
class _SelectOptionCell extends StatefulWidget {
|
||||||
final SelectOptionPB option;
|
final SelectOptionPB option;
|
||||||
final bool isSelected;
|
final bool isSelected;
|
||||||
const _SelectOptionCell(this.option, this.isSelected, {Key? key})
|
const _SelectOptionCell(this.option, this.isSelected, {Key? key})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
State<_SelectOptionCell> createState() => _SelectOptionCellState();
|
||||||
final theme = context.watch<AppTheme>();
|
}
|
||||||
return SizedBox(
|
|
||||||
height: GridSize.typeOptionItemHeight,
|
class _SelectOptionCellState extends State<_SelectOptionCell> {
|
||||||
child: Row(
|
late PopoverController _popoverController;
|
||||||
children: [
|
|
||||||
Flexible(
|
@override
|
||||||
fit: FlexFit.loose,
|
void initState() {
|
||||||
child: SelectOptionTagCell(
|
_popoverController = PopoverController();
|
||||||
option: option,
|
super.initState();
|
||||||
onSelected: (option) {
|
|
||||||
context
|
|
||||||
.read<SelectOptionCellEditorBloc>()
|
|
||||||
.add(SelectOptionEditorEvent.selectOption(option.id));
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
if (isSelected)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(right: 6),
|
|
||||||
child: svgWidget("grid/checkmark"),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FlowyIconButton(
|
|
||||||
width: 30,
|
|
||||||
onPressed: () => _showEditPannel(context),
|
|
||||||
iconPadding: const EdgeInsets.fromLTRB(4, 4, 4, 4),
|
|
||||||
icon: svgWidget("editor/details", color: theme.iconColor),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showEditPannel(BuildContext context) {
|
@override
|
||||||
final pannel = SelectOptionTypeOptionEditor(
|
Widget build(BuildContext context) {
|
||||||
option: option,
|
final theme = context.watch<AppTheme>();
|
||||||
onDeleted: () {
|
return Popover(
|
||||||
context
|
controller: _popoverController,
|
||||||
.read<SelectOptionCellEditorBloc>()
|
offset: const Offset(20, 0),
|
||||||
.add(SelectOptionEditorEvent.deleteOption(option));
|
child: SizedBox(
|
||||||
},
|
height: GridSize.typeOptionItemHeight,
|
||||||
onUpdated: (updatedOption) {
|
child: Row(
|
||||||
context
|
children: [
|
||||||
.read<SelectOptionCellEditorBloc>()
|
Flexible(
|
||||||
.add(SelectOptionEditorEvent.updateOption(updatedOption));
|
fit: FlexFit.loose,
|
||||||
},
|
child: SelectOptionTagCell(
|
||||||
key: ValueKey(option
|
option: widget.option,
|
||||||
.id), // Use ValueKey to refresh the UI, otherwise, it will remain the old value.
|
onSelected: (option) {
|
||||||
);
|
context
|
||||||
final overlayIdentifier = (SelectOptionTypeOptionEditor).toString();
|
.read<SelectOptionCellEditorBloc>()
|
||||||
|
.add(SelectOptionEditorEvent.selectOption(option.id));
|
||||||
FlowyOverlay.of(context).remove(overlayIdentifier);
|
},
|
||||||
FlowyOverlay.of(context).insertWithAnchor(
|
children: [
|
||||||
widget: OverlayContainer(
|
if (widget.isSelected)
|
||||||
child: pannel,
|
Padding(
|
||||||
constraints: BoxConstraints.loose(const Size(200, 300)),
|
padding: const EdgeInsets.only(right: 6),
|
||||||
|
child: svgWidget("grid/checkmark"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FlowyIconButton(
|
||||||
|
width: 30,
|
||||||
|
onPressed: () => _popoverController.show(),
|
||||||
|
iconPadding: const EdgeInsets.fromLTRB(4, 4, 4, 4),
|
||||||
|
icon: svgWidget("editor/details", color: theme.iconColor),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
identifier: overlayIdentifier,
|
popupBuilder: (BuildContext popoverContext) {
|
||||||
anchorContext: context,
|
return OverlayContainer(
|
||||||
anchorDirection: AnchorDirection.rightWithCenterAligned,
|
constraints: BoxConstraints.loose(const Size(200, 300)),
|
||||||
anchorOffset: Offset(2 * overlayContainerPadding.left, 0),
|
child: SelectOptionTypeOptionEditor(
|
||||||
|
option: widget.option,
|
||||||
|
onDeleted: () {
|
||||||
|
context
|
||||||
|
.read<SelectOptionCellEditorBloc>()
|
||||||
|
.add(SelectOptionEditorEvent.deleteOption(widget.option));
|
||||||
|
},
|
||||||
|
onUpdated: (updatedOption) {
|
||||||
|
context
|
||||||
|
.read<SelectOptionCellEditorBloc>()
|
||||||
|
.add(SelectOptionEditorEvent.updateOption(updatedOption));
|
||||||
|
},
|
||||||
|
key: ValueKey(widget.option
|
||||||
|
.id), // Use ValueKey to refresh the UI, otherwise, it will remain the old value.
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ class _GridFieldCellState extends State<GridFieldCell> {
|
|||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final button = Popover(
|
final button = Popover(
|
||||||
controller: popover,
|
controller: popover,
|
||||||
|
direction: PopoverDirection.bottomWithLeftAligned,
|
||||||
child: FieldCellButton(
|
child: FieldCellButton(
|
||||||
field: state.field,
|
field: state.field,
|
||||||
onTap: () => popover.show(),
|
onTap: () => popover.show(),
|
||||||
|
@ -2,7 +2,6 @@ import 'package:app_flowy/plugins/grid/application/field/field_editor_bloc.dart'
|
|||||||
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
|
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
|
||||||
import 'package:appflowy_popover/popover.dart';
|
import 'package:appflowy_popover/popover.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -2,8 +2,10 @@ import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
|
|||||||
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
|
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
|
||||||
import 'package:app_flowy/startup/startup.dart';
|
import 'package:app_flowy/startup/startup.dart';
|
||||||
import 'package:app_flowy/plugins/grid/application/prelude.dart';
|
import 'package:app_flowy/plugins/grid/application/prelude.dart';
|
||||||
|
import 'package:appflowy_popover/popover.dart';
|
||||||
import 'package:flowy_infra/image.dart';
|
import 'package:flowy_infra/image.dart';
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
|
import 'package:flowy_infra_ui/flowy_infra_ui_web.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/button.dart';
|
import 'package:flowy_infra_ui/style_widget/button.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
||||||
@ -154,19 +156,25 @@ class CreateFieldButton extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = context.watch<AppTheme>();
|
final theme = context.watch<AppTheme>();
|
||||||
|
|
||||||
return FlowyButton(
|
return Popover(
|
||||||
text: const FlowyText.medium('New column', fontSize: 12),
|
triggerActions: PopoverTriggerActionFlags.click,
|
||||||
hoverColor: theme.shader6,
|
direction: PopoverDirection.bottomWithRightAligned,
|
||||||
onTap: () {
|
child: FlowyButton(
|
||||||
// FieldEditorPopOver.show(
|
text: const FlowyText.medium('New column', fontSize: 12),
|
||||||
// context,
|
hoverColor: theme.shader6,
|
||||||
// anchorContext: context,
|
onTap: () {},
|
||||||
// gridId: gridId,
|
leftIcon: svgWidget("home/add"),
|
||||||
// fieldName: "",
|
),
|
||||||
// typeOptionLoader: NewFieldTypeOptionLoader(gridId: gridId),
|
popupBuilder: (BuildContext popover) {
|
||||||
// )
|
return OverlayContainer(
|
||||||
|
constraints: BoxConstraints.loose(const Size(240, 200)),
|
||||||
|
child: FieldEditor(
|
||||||
|
gridId: gridId,
|
||||||
|
fieldName: "",
|
||||||
|
typeOptionLoader: NewFieldTypeOptionLoader(gridId: gridId),
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
leftIcon: svgWidget("home/add"),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,7 @@ class DateTypeOptionWidget extends TypeOptionWidget {
|
|||||||
context
|
context
|
||||||
.read<DateTypeOptionBloc>()
|
.read<DateTypeOptionBloc>()
|
||||||
.add(DateTypeOptionEvent.didSelectDateFormat(format));
|
.add(DateTypeOptionEvent.didSelectDateFormat(format));
|
||||||
|
PopoverContainerState.of(popoverContext).closeAll();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -100,7 +101,7 @@ class DateTypeOptionWidget extends TypeOptionWidget {
|
|||||||
context
|
context
|
||||||
.read<DateTypeOptionBloc>()
|
.read<DateTypeOptionBloc>()
|
||||||
.add(DateTypeOptionEvent.didSelectTimeFormat(format));
|
.add(DateTypeOptionEvent.didSelectTimeFormat(format));
|
||||||
PopoverContainerState.of(popoverContext).close();
|
PopoverContainerState.of(popoverContext).closeAll();
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'package:app_flowy/plugins/grid/application/field/type_option/multi_select_type_option.dart';
|
import 'package:app_flowy/plugins/grid/application/field/type_option/multi_select_type_option.dart';
|
||||||
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
|
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:appflowy_popover/popover.dart';
|
||||||
|
|
||||||
import '../field_type_option_editor.dart';
|
import '../field_type_option_editor.dart';
|
||||||
import 'builder.dart';
|
import 'builder.dart';
|
||||||
@ -39,7 +40,10 @@ class MultiSelectTypeOptionWidget extends TypeOptionWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SelectOptionTypeOptionWidget(
|
return SelectOptionTypeOptionWidget(
|
||||||
options: selectOptionAction.typeOption.options,
|
options: selectOptionAction.typeOption.options,
|
||||||
beginEdit: () => overlayDelegate.hideOverlay(context),
|
beginEdit: () {
|
||||||
|
overlayDelegate.hideOverlay(context);
|
||||||
|
PopoverContainerState.of(context).closeAll();
|
||||||
|
},
|
||||||
overlayDelegate: overlayDelegate,
|
overlayDelegate: overlayDelegate,
|
||||||
typeOptionAction: selectOptionAction,
|
typeOptionAction: selectOptionAction,
|
||||||
// key: ValueKey(state.typeOption.hashCode),
|
// key: ValueKey(state.typeOption.hashCode),
|
||||||
|
@ -79,7 +79,7 @@ class NumberTypeOptionWidget extends TypeOptionWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
popupBuilder: (BuildContext context) {
|
popupBuilder: (BuildContext popoverContext) {
|
||||||
return OverlayContainer(
|
return OverlayContainer(
|
||||||
constraints: BoxConstraints.loose(const Size(460, 440)),
|
constraints: BoxConstraints.loose(const Size(460, 440)),
|
||||||
child: NumberFormatList(
|
child: NumberFormatList(
|
||||||
@ -87,6 +87,7 @@ class NumberTypeOptionWidget extends TypeOptionWidget {
|
|||||||
context
|
context
|
||||||
.read<NumberTypeOptionBloc>()
|
.read<NumberTypeOptionBloc>()
|
||||||
.add(NumberTypeOptionEvent.didSelectFormat(format));
|
.add(NumberTypeOptionEvent.didSelectFormat(format));
|
||||||
|
PopoverContainerState.of(popoverContext).closeAll();
|
||||||
},
|
},
|
||||||
selectedFormat: state.typeOption.format,
|
selectedFormat: state.typeOption.format,
|
||||||
),
|
),
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import 'package:app_flowy/plugins/grid/application/field/type_option/select_option_type_option_bloc.dart';
|
import 'package:app_flowy/plugins/grid/application/field/type_option/select_option_type_option_bloc.dart';
|
||||||
|
import 'package:appflowy_popover/popover.dart';
|
||||||
import 'package:flowy_infra/image.dart';
|
import 'package:flowy_infra/image.dart';
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
|
import 'package:flowy_infra_ui/flowy_infra_ui_web.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/button.dart';
|
import 'package:flowy_infra_ui/style_widget/button.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
@ -143,54 +145,70 @@ class _OptionList extends StatelessWidget {
|
|||||||
_OptionCell _makeOptionCell(BuildContext context, SelectOptionPB option) {
|
_OptionCell _makeOptionCell(BuildContext context, SelectOptionPB option) {
|
||||||
return _OptionCell(
|
return _OptionCell(
|
||||||
option: option,
|
option: option,
|
||||||
onSelected: (option) {
|
|
||||||
final pannel = SelectOptionTypeOptionEditor(
|
|
||||||
option: option,
|
|
||||||
onDeleted: () {
|
|
||||||
delegate.hideOverlay(context);
|
|
||||||
context
|
|
||||||
.read<SelectOptionTypeOptionBloc>()
|
|
||||||
.add(SelectOptionTypeOptionEvent.deleteOption(option));
|
|
||||||
},
|
|
||||||
onUpdated: (updatedOption) {
|
|
||||||
delegate.hideOverlay(context);
|
|
||||||
context
|
|
||||||
.read<SelectOptionTypeOptionBloc>()
|
|
||||||
.add(SelectOptionTypeOptionEvent.updateOption(updatedOption));
|
|
||||||
},
|
|
||||||
key: ValueKey(option.id),
|
|
||||||
);
|
|
||||||
delegate.showOverlay(context, pannel);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _OptionCell extends StatelessWidget {
|
class _OptionCell extends StatefulWidget {
|
||||||
final SelectOptionPB option;
|
final SelectOptionPB option;
|
||||||
final Function(SelectOptionPB) onSelected;
|
const _OptionCell({required this.option, Key? key}) : super(key: key);
|
||||||
const _OptionCell({
|
|
||||||
required this.option,
|
@override
|
||||||
required this.onSelected,
|
State<_OptionCell> createState() => _OptionCellState();
|
||||||
Key? key,
|
}
|
||||||
}) : super(key: key);
|
|
||||||
|
class _OptionCellState extends State<_OptionCell> {
|
||||||
|
late PopoverController _popoverController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_popoverController = PopoverController();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = context.watch<AppTheme>();
|
final theme = context.watch<AppTheme>();
|
||||||
|
|
||||||
return SizedBox(
|
return Popover(
|
||||||
height: GridSize.typeOptionItemHeight,
|
controller: _popoverController,
|
||||||
child: SelectOptionTagCell(
|
offset: const Offset(20, 0),
|
||||||
option: option,
|
child: SizedBox(
|
||||||
onSelected: onSelected,
|
height: GridSize.typeOptionItemHeight,
|
||||||
children: [
|
child: SelectOptionTagCell(
|
||||||
svgWidget(
|
option: widget.option,
|
||||||
"grid/details",
|
onSelected: (SelectOptionPB pb) {
|
||||||
color: theme.iconColor,
|
_popoverController.show();
|
||||||
),
|
},
|
||||||
],
|
children: [
|
||||||
|
svgWidget(
|
||||||
|
"grid/details",
|
||||||
|
color: theme.iconColor,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
popupBuilder: (BuildContext popoverContext) {
|
||||||
|
return OverlayContainer(
|
||||||
|
constraints: BoxConstraints.loose(const Size(460, 440)),
|
||||||
|
child: SelectOptionTypeOptionEditor(
|
||||||
|
option: widget.option,
|
||||||
|
onDeleted: () {
|
||||||
|
context
|
||||||
|
.read<SelectOptionTypeOptionBloc>()
|
||||||
|
.add(SelectOptionTypeOptionEvent.deleteOption(widget.option));
|
||||||
|
PopoverContainerState.of(popoverContext).closeAll();
|
||||||
|
},
|
||||||
|
onUpdated: (updatedOption) {
|
||||||
|
context
|
||||||
|
.read<SelectOptionTypeOptionBloc>()
|
||||||
|
.add(SelectOptionTypeOptionEvent.updateOption(updatedOption));
|
||||||
|
PopoverContainerState.of(popoverContext).closeAll();
|
||||||
|
},
|
||||||
|
key: ValueKey(widget.option.id),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import 'package:app_flowy/plugins/grid/application/field/type_option/single_sele
|
|||||||
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
|
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '../field_type_option_editor.dart';
|
import '../field_type_option_editor.dart';
|
||||||
|
import 'package:appflowy_popover/popover.dart';
|
||||||
import 'builder.dart';
|
import 'builder.dart';
|
||||||
import 'select_option.dart';
|
import 'select_option.dart';
|
||||||
|
|
||||||
@ -38,7 +39,10 @@ class SingleSelectTypeOptionWidget extends TypeOptionWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SelectOptionTypeOptionWidget(
|
return SelectOptionTypeOptionWidget(
|
||||||
options: selectOptionAction.typeOption.options,
|
options: selectOptionAction.typeOption.options,
|
||||||
beginEdit: () => overlayDelegate.hideOverlay(context),
|
beginEdit: () {
|
||||||
|
overlayDelegate.hideOverlay(context);
|
||||||
|
PopoverContainerState.of(context).closeAll();
|
||||||
|
},
|
||||||
overlayDelegate: overlayDelegate,
|
overlayDelegate: overlayDelegate,
|
||||||
typeOptionAction: selectOptionAction,
|
typeOptionAction: selectOptionAction,
|
||||||
// key: ValueKey(state.typeOption.hashCode),
|
// key: ValueKey(state.typeOption.hashCode),
|
||||||
|
@ -19,7 +19,7 @@ import 'package:styled_widget/styled_widget.dart';
|
|||||||
import '../../../application/field/field_cache.dart';
|
import '../../../application/field/field_cache.dart';
|
||||||
import '../../layout/sizes.dart';
|
import '../../layout/sizes.dart';
|
||||||
|
|
||||||
class GridPropertyList extends StatelessWidget {
|
class GridPropertyList extends StatefulWidget {
|
||||||
final String gridId;
|
final String gridId;
|
||||||
final GridFieldCache fieldCache;
|
final GridFieldCache fieldCache;
|
||||||
const GridPropertyList({
|
const GridPropertyList({
|
||||||
@ -28,17 +28,34 @@ class GridPropertyList extends StatelessWidget {
|
|||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() => _GridPropertyListState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _GridPropertyListState extends State<GridPropertyList> {
|
||||||
|
late PopoverMutex _popoverMutex;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_popoverMutex = PopoverMutex();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) =>
|
create: (context) => getIt<GridPropertyBloc>(
|
||||||
getIt<GridPropertyBloc>(param1: gridId, param2: fieldCache)
|
param1: widget.gridId, param2: widget.fieldCache)
|
||||||
..add(const GridPropertyEvent.initial()),
|
..add(const GridPropertyEvent.initial()),
|
||||||
child: BlocBuilder<GridPropertyBloc, GridPropertyState>(
|
child: BlocBuilder<GridPropertyBloc, GridPropertyState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final cells = state.fields.map((field) {
|
final cells = state.fields.map((field) {
|
||||||
return _GridPropertyCell(
|
return _GridPropertyCell(
|
||||||
gridId: gridId, field: field, key: ValueKey(field.id));
|
popoverMutex: _popoverMutex,
|
||||||
|
gridId: widget.gridId,
|
||||||
|
field: field,
|
||||||
|
key: ValueKey(field.id),
|
||||||
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
return ListView.separated(
|
return ListView.separated(
|
||||||
@ -60,8 +77,13 @@ class GridPropertyList extends StatelessWidget {
|
|||||||
class _GridPropertyCell extends StatelessWidget {
|
class _GridPropertyCell extends StatelessWidget {
|
||||||
final FieldPB field;
|
final FieldPB field;
|
||||||
final String gridId;
|
final String gridId;
|
||||||
const _GridPropertyCell({required this.gridId, required this.field, Key? key})
|
final PopoverMutex popoverMutex;
|
||||||
: super(key: key);
|
const _GridPropertyCell({
|
||||||
|
required this.gridId,
|
||||||
|
required this.field,
|
||||||
|
required this.popoverMutex,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -95,6 +117,7 @@ class _GridPropertyCell extends StatelessWidget {
|
|||||||
|
|
||||||
Widget _editFieldButton(AppTheme theme, BuildContext context) {
|
Widget _editFieldButton(AppTheme theme, BuildContext context) {
|
||||||
return Popover(
|
return Popover(
|
||||||
|
mutex: popoverMutex,
|
||||||
triggerActions: PopoverTriggerActionFlags.click,
|
triggerActions: PopoverTriggerActionFlags.click,
|
||||||
offset: const Offset(20, 0),
|
offset: const Offset(20, 0),
|
||||||
child: FlowyButton(
|
child: FlowyButton(
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
import 'dart:ui';
|
|
||||||
|
|
||||||
import 'package:appflowy_popover/layout.dart';
|
import 'package:appflowy_popover/layout.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import './follower.dart';
|
|
||||||
|
|
||||||
class PopoverMutex {
|
class PopoverMutex {
|
||||||
PopoverState? state;
|
PopoverState? state;
|
||||||
@ -128,6 +125,7 @@ class PopoverState extends State<Popover> {
|
|||||||
offset: widget.offset ?? Offset.zero,
|
offset: widget.offset ?? Offset.zero,
|
||||||
popupBuilder: widget.popupBuilder,
|
popupBuilder: widget.popupBuilder,
|
||||||
onClose: () => close(),
|
onClose: () => close(),
|
||||||
|
onCloseAll: () => closeAll(),
|
||||||
));
|
));
|
||||||
|
|
||||||
return Stack(children: children);
|
return Stack(children: children);
|
||||||
@ -155,6 +153,10 @@ class PopoverState extends State<Popover> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closeAll() {
|
||||||
|
_popoverWithMask?.close();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void deactivate() {
|
void deactivate() {
|
||||||
debugPrint("deactivate");
|
debugPrint("deactivate");
|
||||||
@ -247,6 +249,7 @@ class PopoverContainer extends StatefulWidget {
|
|||||||
final PopoverLink popoverLink;
|
final PopoverLink popoverLink;
|
||||||
final Offset offset;
|
final Offset offset;
|
||||||
final void Function() onClose;
|
final void Function() onClose;
|
||||||
|
final void Function() onCloseAll;
|
||||||
|
|
||||||
const PopoverContainer({
|
const PopoverContainer({
|
||||||
Key? key,
|
Key? key,
|
||||||
@ -255,6 +258,7 @@ class PopoverContainer extends StatefulWidget {
|
|||||||
required this.popoverLink,
|
required this.popoverLink,
|
||||||
required this.offset,
|
required this.offset,
|
||||||
required this.onClose,
|
required this.onClose,
|
||||||
|
required this.onCloseAll,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -274,9 +278,9 @@ class PopoverContainerState extends State<PopoverContainer> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() => widget.onClose();
|
||||||
widget.onClose();
|
|
||||||
}
|
closeAll() => widget.onCloseAll();
|
||||||
|
|
||||||
static PopoverContainerState of(BuildContext context) {
|
static PopoverContainerState of(BuildContext context) {
|
||||||
if (context is StatefulElement && context.state is PopoverContainerState) {
|
if (context is StatefulElement && context.state is PopoverContainerState) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user