mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-11-29 16:50:09 +00:00
feat: use popover in date cell
This commit is contained in:
parent
01a79c69c3
commit
6ef7b6cf68
@ -3,6 +3,7 @@ import 'package:flutter/widgets.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.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 '../cell_builder.dart';
|
import '../cell_builder.dart';
|
||||||
import 'date_editor.dart';
|
import 'date_editor.dart';
|
||||||
@ -39,10 +40,12 @@ class GridDateCell extends GridCellWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _DateCellState extends GridCellState<GridDateCell> {
|
class _DateCellState extends GridCellState<GridDateCell> {
|
||||||
|
late PopoverController _popover;
|
||||||
late DateCellBloc _cellBloc;
|
late DateCellBloc _cellBloc;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
_popover = PopoverController();
|
||||||
final cellController = widget.cellControllerBuilder.build();
|
final cellController = widget.cellControllerBuilder.build();
|
||||||
_cellBloc = getIt<DateCellBloc>(param1: cellController)
|
_cellBloc = getIt<DateCellBloc>(param1: cellController)
|
||||||
..add(const DateCellEvent.initial());
|
..add(const DateCellEvent.initial());
|
||||||
@ -58,19 +61,35 @@ class _DateCellState extends GridCellState<GridDateCell> {
|
|||||||
value: _cellBloc,
|
value: _cellBloc,
|
||||||
child: BlocBuilder<DateCellBloc, DateCellState>(
|
child: BlocBuilder<DateCellBloc, DateCellState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return SizedBox.expand(
|
return Popover(
|
||||||
child: GestureDetector(
|
controller: _popover,
|
||||||
behavior: HitTestBehavior.opaque,
|
targetAnchor: Alignment.bottomLeft,
|
||||||
onTap: () => _showCalendar(context),
|
followerAnchor: Alignment.topLeft,
|
||||||
child: MouseRegion(
|
offset: const Offset(0, 20),
|
||||||
opaque: false,
|
child: SizedBox.expand(
|
||||||
cursor: SystemMouseCursors.click,
|
child: GestureDetector(
|
||||||
child: Align(
|
behavior: HitTestBehavior.opaque,
|
||||||
alignment: alignment,
|
onTap: () => _showCalendar(context),
|
||||||
child: FlowyText.medium(state.dateStr, fontSize: 12),
|
child: MouseRegion(
|
||||||
|
opaque: false,
|
||||||
|
cursor: SystemMouseCursors.click,
|
||||||
|
child: Align(
|
||||||
|
alignment: alignment,
|
||||||
|
child: FlowyText.medium(state.dateStr, fontSize: 12),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
popupBuilder: (BuildContext popoverContent) {
|
||||||
|
final bloc = context.read<DateCellBloc>();
|
||||||
|
return DateCellEditor(
|
||||||
|
cellController: bloc.cellController.clone(),
|
||||||
|
onDismissed: () => widget.onCellEditing.value = false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onClose: () {
|
||||||
|
widget.onCellEditing.value = false;
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -78,14 +97,7 @@ class _DateCellState extends GridCellState<GridDateCell> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _showCalendar(BuildContext context) {
|
void _showCalendar(BuildContext context) {
|
||||||
final bloc = context.read<DateCellBloc>();
|
_popover.show();
|
||||||
widget.onCellEditing.value = true;
|
|
||||||
final calendar =
|
|
||||||
DateCellEditor(onDismissed: () => widget.onCellEditing.value = false);
|
|
||||||
calendar.show(
|
|
||||||
context,
|
|
||||||
cellController: bloc.cellController.clone(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import 'package:app_flowy/generated/locale_keys.g.dart';
|
import 'package:app_flowy/generated/locale_keys.g.dart';
|
||||||
import 'package:app_flowy/plugins/grid/application/cell/date_cal_bloc.dart';
|
import 'package:app_flowy/plugins/grid/application/cell/date_cal_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:app_flowy/startup/tasks/platform_service.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.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';
|
||||||
@ -23,58 +24,54 @@ final kFirstDay = DateTime(kToday.year, kToday.month - 3, kToday.day);
|
|||||||
final kLastDay = DateTime(kToday.year, kToday.month + 3, kToday.day);
|
final kLastDay = DateTime(kToday.year, kToday.month + 3, kToday.day);
|
||||||
const kMargin = EdgeInsets.symmetric(horizontal: 6, vertical: 10);
|
const kMargin = EdgeInsets.symmetric(horizontal: 6, vertical: 10);
|
||||||
|
|
||||||
class DateCellEditor with FlowyOverlayDelegate {
|
class DateCellEditor extends StatefulWidget {
|
||||||
final VoidCallback onDismissed;
|
final VoidCallback onDismissed;
|
||||||
|
final GridDateCellController cellController;
|
||||||
|
|
||||||
const DateCellEditor({
|
const DateCellEditor({
|
||||||
|
Key? key,
|
||||||
required this.onDismissed,
|
required this.onDismissed,
|
||||||
});
|
required this.cellController,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
Future<void> show(
|
@override
|
||||||
BuildContext context, {
|
State<StatefulWidget> createState() => _DateCellEditor();
|
||||||
required GridDateCellController cellController,
|
}
|
||||||
}) async {
|
|
||||||
DateCellEditor.remove(context);
|
|
||||||
|
|
||||||
final result =
|
class _DateCellEditor extends State<DateCellEditor> {
|
||||||
await cellController.getFieldTypeOption(DateTypeOptionDataParser());
|
DateTypeOptionPB? _dateTypeOptionPB;
|
||||||
|
|
||||||
result.fold(
|
@override
|
||||||
(dateTypeOptionPB) {
|
void initState() {
|
||||||
final calendar = _CellCalendarWidget(
|
super.initState();
|
||||||
cellContext: cellController,
|
_fetchData();
|
||||||
dateTypeOptionPB: dateTypeOptionPB,
|
}
|
||||||
);
|
|
||||||
|
|
||||||
FlowyOverlay.of(context).insertWithAnchor(
|
_fetchData() async {
|
||||||
widget: OverlayContainer(
|
final result = await widget.cellController
|
||||||
child: calendar,
|
.getFieldTypeOption(DateTypeOptionDataParser());
|
||||||
constraints: BoxConstraints.loose(const Size(320, 500)),
|
|
||||||
),
|
result.fold((dateTypeOptionPB) {
|
||||||
identifier: DateCellEditor.identifier(),
|
setState(() {
|
||||||
anchorContext: context,
|
_dateTypeOptionPB = dateTypeOptionPB;
|
||||||
anchorDirection: AnchorDirection.leftWithCenterAligned,
|
});
|
||||||
style: FlowyOverlayStyle(blur: false),
|
}, (err) => Log.error(err));
|
||||||
delegate: this,
|
}
|
||||||
);
|
|
||||||
},
|
@override
|
||||||
(err) => Log.error(err),
|
Widget build(BuildContext context) {
|
||||||
|
if (_dateTypeOptionPB == null) {
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
|
||||||
|
return OverlayContainer(
|
||||||
|
child: _CellCalendarWidget(
|
||||||
|
cellContext: widget.cellController,
|
||||||
|
dateTypeOptionPB: _dateTypeOptionPB!,
|
||||||
|
),
|
||||||
|
constraints: BoxConstraints.loose(const Size(320, 500)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remove(BuildContext context) {
|
|
||||||
FlowyOverlay.of(context).remove(identifier());
|
|
||||||
}
|
|
||||||
|
|
||||||
static String identifier() {
|
|
||||||
return (DateCellEditor).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didRemove() => onDismissed();
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool asBarrier() => true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CellCalendarWidget extends StatelessWidget {
|
class _CellCalendarWidget extends StatelessWidget {
|
||||||
|
|||||||
@ -37,6 +37,7 @@ class Popover extends StatefulWidget {
|
|||||||
final Alignment targetAnchor;
|
final Alignment targetAnchor;
|
||||||
final Alignment followerAnchor;
|
final Alignment followerAnchor;
|
||||||
final Widget Function(BuildContext context) popupBuilder;
|
final Widget Function(BuildContext context) popupBuilder;
|
||||||
|
final void Function()? onClose;
|
||||||
|
|
||||||
const Popover({
|
const Popover({
|
||||||
Key? key,
|
Key? key,
|
||||||
@ -47,6 +48,7 @@ class Popover extends StatefulWidget {
|
|||||||
this.maskDecoration,
|
this.maskDecoration,
|
||||||
this.targetAnchor = Alignment.topLeft,
|
this.targetAnchor = Alignment.topLeft,
|
||||||
this.followerAnchor = Alignment.topLeft,
|
this.followerAnchor = Alignment.topLeft,
|
||||||
|
this.onClose,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -71,15 +73,9 @@ class PopoverState extends State<Popover> {
|
|||||||
_recognizer.onTap = (() {
|
_recognizer.onTap = (() {
|
||||||
debugPrint("ggg tap");
|
debugPrint("ggg tap");
|
||||||
});
|
});
|
||||||
WidgetsBinding.instance.pointerRouter
|
|
||||||
.addGlobalRoute(_handleGlobalPointerEvent);
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleGlobalPointerEvent(PointerEvent event) {
|
|
||||||
// debugPrint("mouse down: ${event}");
|
|
||||||
}
|
|
||||||
|
|
||||||
showOverlay() {
|
showOverlay() {
|
||||||
debugPrint("show overlay");
|
debugPrint("show overlay");
|
||||||
close();
|
close();
|
||||||
@ -126,14 +122,15 @@ class PopoverState extends State<Popover> {
|
|||||||
if (_popoverWithMask == this) {
|
if (_popoverWithMask == this) {
|
||||||
_popoverWithMask = null;
|
_popoverWithMask = null;
|
||||||
}
|
}
|
||||||
|
if (widget.onClose != null) {
|
||||||
|
widget.onClose!();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void deactivate() {
|
void deactivate() {
|
||||||
debugPrint("deactivate");
|
debugPrint("deactivate");
|
||||||
WidgetsBinding.instance.pointerRouter
|
|
||||||
.removeGlobalRoute(_handleGlobalPointerEvent);
|
|
||||||
close();
|
close();
|
||||||
super.deactivate();
|
super.deactivate();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user