mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: double click to select / unselect options (#4094)
Co-authored-by: Richard Shiue <71320345+richardshiue@users.noreply.github.com>
This commit is contained in:
parent
7d55153475
commit
48d6967d3b
@ -1,13 +1,11 @@
|
|||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database2/select_option.pb.dart';
|
|
||||||
|
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
|
||||||
import 'package:flowy_infra/size.dart';
|
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
|
||||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-database2/select_option.pb.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flowy_infra/size.dart';
|
||||||
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
extension SelectOptionColorExtension on SelectOptionColorPB {
|
extension SelectOptionColorExtension on SelectOptionColorPB {
|
||||||
Color toColor(BuildContext context) {
|
Color toColor(BuildContext context) {
|
||||||
@ -131,33 +129,28 @@ class SelectOptionTagCell extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FlowyHover(
|
return Row(
|
||||||
style: HoverStyle(
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
children: [
|
||||||
),
|
Expanded(
|
||||||
child: Row(
|
child: GestureDetector(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
behavior: HitTestBehavior.opaque,
|
||||||
children: [
|
onTap: onSelected,
|
||||||
Expanded(
|
child: Align(
|
||||||
child: GestureDetector(
|
alignment: AlignmentDirectional.centerStart,
|
||||||
behavior: HitTestBehavior.opaque,
|
child: Padding(
|
||||||
onTap: onSelected,
|
padding: const EdgeInsets.all(5.0),
|
||||||
child: Align(
|
child: SelectOptionTag(
|
||||||
alignment: AlignmentDirectional.centerStart,
|
option: option,
|
||||||
child: Padding(
|
padding:
|
||||||
padding: const EdgeInsets.all(5.0),
|
const EdgeInsets.symmetric(horizontal: 8, vertical: 1),
|
||||||
child: SelectOptionTag(
|
|
||||||
option: option,
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.symmetric(horizontal: 8, vertical: 1),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
...children,
|
),
|
||||||
],
|
...children,
|
||||||
),
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,9 @@ import 'package:appflowy/plugins/database_view/application/cell/cell_controller_
|
|||||||
import 'package:appflowy_backend/protobuf/flowy-database2/select_option.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database2/select_option.pb.dart';
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
import 'package:flowy_infra_ui/style_widget/hover.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';
|
||||||
import 'package:textfield_tags/textfield_tags.dart';
|
import 'package:textfield_tags/textfield_tags.dart';
|
||||||
@ -340,9 +340,16 @@ class _SelectOptionCellState extends State<_SelectOptionCell> {
|
|||||||
asBarrier: true,
|
asBarrier: true,
|
||||||
constraints: BoxConstraints.loose(const Size(200, 470)),
|
constraints: BoxConstraints.loose(const Size(200, 470)),
|
||||||
mutex: widget.popoverMutex,
|
mutex: widget.popoverMutex,
|
||||||
|
clickHandler: PopoverClickHandler.gestureDetector,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||||
child: child,
|
child: FlowyHover(
|
||||||
|
resetHoverOnRebuild: false,
|
||||||
|
style: HoverStyle(
|
||||||
|
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||||
|
),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
popupBuilder: (BuildContext popoverContext) {
|
popupBuilder: (BuildContext popoverContext) {
|
||||||
return SelectOptionTypeOptionEditor(
|
return SelectOptionTypeOptionEditor(
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:appflowy/plugins/database_view/application/cell/cell_controller_builder.dart';
|
import 'package:appflowy/plugins/database_view/application/cell/cell_controller_builder.dart';
|
||||||
|
import 'package:appflowy_backend/log.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:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:appflowy_backend/log.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
import '../../../../application/cell/select_option_cell_service.dart';
|
import '../../../../application/cell/select_option_cell_service.dart';
|
||||||
|
|
||||||
part 'select_option_editor_bloc.freezed.dart';
|
part 'select_option_editor_bloc.freezed.dart';
|
||||||
@ -61,9 +63,27 @@ class SelectOptionCellEditorBloc
|
|||||||
},
|
},
|
||||||
selectOption: (_SelectOption value) async {
|
selectOption: (_SelectOption value) async {
|
||||||
await _selectOptionService.select(optionIds: [value.optionId]);
|
await _selectOptionService.select(optionIds: [value.optionId]);
|
||||||
|
final selectedOption = [
|
||||||
|
...state.selectedOptions,
|
||||||
|
state.options.firstWhere(
|
||||||
|
(element) => element.id == value.optionId,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
selectedOptions: selectedOption,
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
unSelectOption: (_UnSelectOption value) async {
|
unSelectOption: (_UnSelectOption value) async {
|
||||||
await _selectOptionService.unSelect(optionIds: [value.optionId]);
|
await _selectOptionService.unSelect(optionIds: [value.optionId]);
|
||||||
|
final selectedOptions = [...state.selectedOptions]
|
||||||
|
..removeWhere((e) => e.id == value.optionId);
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
selectedOptions: selectedOptions,
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
trySelectOption: (_TrySelectOption value) {
|
trySelectOption: (_TrySelectOption value) {
|
||||||
_trySelectOption(value.optionName, emit);
|
_trySelectOption(value.optionName, emit);
|
||||||
|
@ -138,7 +138,7 @@ class _PropertyCellState extends State<_PropertyCell> {
|
|||||||
final PopoverController _popoverController = PopoverController();
|
final PopoverController _popoverController = PopoverController();
|
||||||
final PopoverController _fieldPopoverController = PopoverController();
|
final PopoverController _fieldPopoverController = PopoverController();
|
||||||
|
|
||||||
bool _isFieldHover = false;
|
final ValueNotifier<bool> _isFieldHover = ValueNotifier(false);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -159,15 +159,19 @@ class _PropertyCellState extends State<_PropertyCell> {
|
|||||||
triggerActions: PopoverTriggerFlags.none,
|
triggerActions: PopoverTriggerFlags.none,
|
||||||
direction: PopoverDirection.bottomWithLeftAligned,
|
direction: PopoverDirection.bottomWithLeftAligned,
|
||||||
popupBuilder: (popoverContext) => buildFieldEditor(),
|
popupBuilder: (popoverContext) => buildFieldEditor(),
|
||||||
child: _isFieldHover
|
child: ValueListenableBuilder(
|
||||||
? BlockActionButton(
|
valueListenable: _isFieldHover,
|
||||||
onTap: () => _fieldPopoverController.show(),
|
builder: ((context, value, child) {
|
||||||
svg: FlowySvgs.drag_element_s,
|
return value ? child! : const SizedBox.shrink();
|
||||||
richMessage: TextSpan(
|
}),
|
||||||
text: LocaleKeys.grid_rowPage_fieldDragElementTooltip.tr(),
|
child: BlockActionButton(
|
||||||
),
|
onTap: () => _fieldPopoverController.show(),
|
||||||
)
|
svg: FlowySvgs.drag_element_s,
|
||||||
: const SizedBox.shrink(),
|
richMessage: TextSpan(
|
||||||
|
text: LocaleKeys.grid_rowPage_fieldDragElementTooltip.tr(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -185,16 +189,21 @@ class _PropertyCellState extends State<_PropertyCell> {
|
|||||||
margin: const EdgeInsets.only(bottom: 8),
|
margin: const EdgeInsets.only(bottom: 8),
|
||||||
constraints: const BoxConstraints(minHeight: 30),
|
constraints: const BoxConstraints(minHeight: 30),
|
||||||
child: MouseRegion(
|
child: MouseRegion(
|
||||||
onEnter: (event) => setState(() => _isFieldHover = true),
|
onEnter: (event) => _isFieldHover.value = true,
|
||||||
onExit: (event) => setState(() => _isFieldHover = false),
|
onExit: (event) => _isFieldHover.value = false,
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
ReorderableDragStartListener(
|
ValueListenableBuilder(
|
||||||
index: widget.index,
|
valueListenable: _isFieldHover,
|
||||||
enabled: _isFieldHover,
|
builder: (context, value, _) {
|
||||||
child: dragThumb,
|
return ReorderableDragStartListener(
|
||||||
|
index: widget.index,
|
||||||
|
enabled: value,
|
||||||
|
child: dragThumb,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
const HSpace(4),
|
const HSpace(4),
|
||||||
AppFlowyPopover(
|
AppFlowyPopover(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user