diff --git a/frontend/app_flowy/packages/appflowy_board/CHANGELOG.md b/frontend/app_flowy/packages/appflowy_board/CHANGELOG.md index 76f33711b1..c4c6495533 100644 --- a/frontend/app_flowy/packages/appflowy_board/CHANGELOG.md +++ b/frontend/app_flowy/packages/appflowy_board/CHANGELOG.md @@ -1,16 +1,21 @@ +# 0.0.5 +* Optimize insert card animation +* Enable insert card at the end of the column +* Fix some bugs + # 0.0.4 -* fix some bugs +* Fix some bugs # 0.0.3 * Support customize UI * Update example * Add AppFlowy style widget -## 0.0.2 +# 0.0.2 * Update documentation -## 0.0.1 +# 0.0.1 * Support drag and drop column * Support drag and drop column items from one to another diff --git a/frontend/app_flowy/packages/appflowy_board/example/lib/multi_board_list_example.dart b/frontend/app_flowy/packages/appflowy_board/example/lib/multi_board_list_example.dart index 01aba725a5..218331d198 100644 --- a/frontend/app_flowy/packages/appflowy_board/example/lib/multi_board_list_example.dart +++ b/frontend/app_flowy/packages/appflowy_board/example/lib/multi_board_list_example.dart @@ -26,13 +26,18 @@ class _MultiBoardListExampleState extends State { List a = [ TextItem("Card 1"), TextItem("Card 2"), - // RichTextItem(title: "Card 3", subtitle: 'Aug 1, 2020 4:05 PM'), + RichTextItem(title: "Card 3", subtitle: 'Aug 1, 2020 4:05 PM'), TextItem("Card 4"), + TextItem("Card 5"), + TextItem("Card 6"), + RichTextItem(title: "Card 7", subtitle: 'Aug 1, 2020 4:05 PM'), + RichTextItem(title: "Card 8", subtitle: 'Aug 1, 2020 4:05 PM'), + TextItem("Card 9"), ]; final column1 = AFBoardColumnData(id: "To Do", items: a); final column2 = AFBoardColumnData(id: "In Progress", items: [ - // RichTextItem(title: "Card 5", subtitle: 'Aug 1, 2020 4:05 PM'), - // TextItem("Card 6"), + RichTextItem(title: "Card 10", subtitle: 'Aug 1, 2020 4:05 PM'), + TextItem("Card 11"), ]); final column3 = AFBoardColumnData(id: "Done", items: []); @@ -93,7 +98,7 @@ class _MultiBoardListExampleState extends State { return Align( alignment: Alignment.centerLeft, child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 40), child: Text(item.s), ), ); diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/utils/log.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/utils/log.dart index 20f810a966..9c23060b26 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/utils/log.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/utils/log.dart @@ -4,8 +4,6 @@ import 'package:flutter/material.dart'; const DART_LOG = "Dart_LOG"; class Log { - // static const enableLog = bool.hasEnvironment(DART_LOG); - // static final shared = Log(); static const enableLog = false; static void info(String? message) { @@ -16,19 +14,19 @@ class Log { static void debug(String? message) { if (enableLog) { - debugPrint('🐛[Debug]=> $message'); + debugPrint('🐛[Debug] - ${DateTime.now().second}=> $message'); } } static void warn(String? message) { if (enableLog) { - debugPrint('🐛[Warn]=> $message'); + debugPrint('🐛[Warn] - ${DateTime.now().second} => $message'); } } static void trace(String? message) { if (enableLog) { - // debugPrint('❗️[Trace]=> $message'); + debugPrint('❗️[Trace] - ${DateTime.now().second}=> $message'); } } } diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board.dart index 20824ba6b9..e07ee39d61 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board.dart @@ -159,7 +159,7 @@ class _BoardContentState extends State { dataSource: widget.dataController, direction: Axis.horizontal, interceptor: interceptor, - children: _buildColumns(), + children: _buildColumns(interceptor.columnKeys), ); return Stack( @@ -191,7 +191,7 @@ class _BoardContentState extends State { ); } - List _buildColumns() { + List _buildColumns(List columnKeys) { final List children = widget.dataController.columnDatas.asMap().entries.map( (item) { @@ -208,21 +208,33 @@ class _BoardContentState extends State { value: widget.dataController.columnController(columnData.id), child: Consumer( builder: (context, value, child) { + final boardColumn = AFBoardColumnWidget( + margin: _marginFromIndex(columnIndex), + itemMargin: widget.config.columnItemPadding, + headerBuilder: widget.headerBuilder, + footBuilder: widget.footBuilder, + cardBuilder: widget.cardBuilder, + dataSource: dataSource, + scrollController: ScrollController(), + phantomController: widget.phantomController, + onReorder: widget.dataController.moveColumnItem, + cornerRadius: widget.config.cornerRadius, + backgroundColor: widget.config.columnBackgroundColor, + ); + + // columnKeys + // .removeWhere((element) => element.columnId == columnData.id); + + // columnKeys.add( + // ColumnKey( + // columnId: columnData.id, + // key: boardColumn.columnGlobalKey, + // ), + // ); + return ConstrainedBox( constraints: widget.columnConstraints, - child: AFBoardColumnWidget( - margin: _marginFromIndex(columnIndex), - itemMargin: widget.config.columnItemPadding, - headerBuilder: widget.headerBuilder, - footBuilder: widget.footBuilder, - cardBuilder: widget.cardBuilder, - dataSource: dataSource, - scrollController: ScrollController(), - phantomController: widget.phantomController, - onReorder: widget.dataController.moveColumnItem, - cornerRadius: widget.config.cornerRadius, - backgroundColor: widget.config.columnBackgroundColor, - ), + child: boardColumn, ); }, ), diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column.dart index cbc537810e..d4e5ff8800 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column.dart @@ -87,7 +87,9 @@ class AFBoardColumnWidget extends StatefulWidget { final Color backgroundColor; - const AFBoardColumnWidget({ + final GlobalKey columnGlobalKey = GlobalKey(); + + AFBoardColumnWidget({ Key? key, this.headerBuilder, this.footBuilder, @@ -136,8 +138,8 @@ class _AFBoardColumnWidgetState extends State { draggableTargetBuilder: PhantomDraggableBuilder(), ); - final reorderFlex = ReorderFlex( - key: widget.key, + Widget reorderFlex = ReorderFlex( + key: widget.columnGlobalKey, scrollController: widget.scrollController, config: widget.config, onDragStarted: (index) { @@ -160,6 +162,9 @@ class _AFBoardColumnWidgetState extends State { children: children, ); + // reorderFlex = + // KeyedSubtree(key: widget.columnGlobalKey, child: reorderFlex); + return Container( margin: widget.margin, clipBehavior: Clip.hardEdge, diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_data.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_data.dart index e8d5471939..a08bba378f 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_data.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_data.dart @@ -197,7 +197,8 @@ class AFBoardDataController extends ChangeNotifier assert(index != -1); if (index != -1) { if (index != newIndex) { - // Log.debug('[$BoardPhantomController] update $toColumnId:$index to $toColumnId:$phantomIndex'); + Log.trace( + '[$BoardPhantomController] update $columnId:$index to $columnId:$newIndex'); final item = columnDataController.removeAt(index, notify: false); columnDataController.insert(newIndex, item, notify: false); } diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_flex/drag_state.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_flex/drag_state.dart index f5f7250834..592277afbc 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_flex/drag_state.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_flex/drag_state.dart @@ -43,7 +43,7 @@ class FlexDragTargetData extends DragTargetData { } class DraggingState { - final String id; + final String reorderFlexId; /// The member of widget.children currently being dragged. Widget? _draggingWidget; @@ -72,7 +72,7 @@ class DraggingState { /// The additional margin to place around a computed drop area. static const double _dropAreaMargin = 0.0; - DraggingState(this.id); + DraggingState(this.reorderFlexId); Size get dropAreaSize { if (feedbackSize == null) { @@ -132,7 +132,7 @@ class DraggingState { } void updateNextIndex(int index) { - Log.trace('updateNextIndex: $index'); + Log.debug('$reorderFlexId updateNextIndex: $index'); nextIndex = index; } diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_flex/drag_target.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_flex/drag_target.dart index 132d3d9bc4..8217d2736f 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_flex/drag_target.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_flex/drag_target.dart @@ -222,10 +222,10 @@ class DragTargetAnimation { value: 0, vsync: vsync, duration: reorderAnimationDuration); insertController = AnimationController( - value: 0.0, vsync: vsync, duration: const Duration(milliseconds: 100)); + value: 0.0, vsync: vsync, duration: const Duration(milliseconds: 200)); deleteController = AnimationController( - value: 0.0, vsync: vsync, duration: const Duration(milliseconds: 10)); + value: 0.0, vsync: vsync, duration: const Duration(milliseconds: 1)); } void startDragging() { @@ -276,6 +276,31 @@ class IgnorePointerWidget extends StatelessWidget { } } +class AbsorbPointerWidget extends StatelessWidget { + final Widget? child; + final bool useIntrinsicSize; + const AbsorbPointerWidget({ + required this.child, + this.useIntrinsicSize = false, + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final sizedChild = useIntrinsicSize + ? child + : SizedBox(width: 0.0, height: 0.0, child: child); + + final opacity = useIntrinsicSize ? 0.3 : 0.0; + return AbsorbPointer( + child: Opacity( + opacity: opacity, + child: sizedChild, + ), + ); + } +} + class PhantomWidget extends StatelessWidget { final Widget? child; final double opacity; @@ -371,6 +396,7 @@ class _DragTargeMovePlaceholderState extends State { } abstract class FakeDragTargetEventTrigger { + void fakeOnDragStart(void Function(int?) callback); void fakeOnDragEnded(VoidCallback callback); } @@ -421,6 +447,10 @@ class _FakeDragTargetState /// Start insert animation widget.insertAnimationController.forward(from: 0.0); + // widget.eventTrigger.fakeOnDragStart((insertIndex) { + // Log.trace("[$FakeDragTarget] on drag $insertIndex"); + // }); + widget.eventTrigger.fakeOnDragEnded(() { WidgetsBinding.instance.addPostFrameCallback((_) { widget.onDragEnded(widget.eventData.dragTargetData as T); @@ -436,7 +466,7 @@ class _FakeDragTargetState return SizeTransitionWithIntrinsicSize( sizeFactor: widget.deleteAnimationController, axis: Axis.vertical, - child: IgnorePointerWidget( + child: AbsorbPointerWidget( child: widget.child, ), ); @@ -444,7 +474,7 @@ class _FakeDragTargetState return SizeTransitionWithIntrinsicSize( sizeFactor: widget.insertAnimationController, axis: Axis.vertical, - child: IgnorePointerWidget( + child: AbsorbPointerWidget( useIntrinsicSize: true, child: widget.child, ), diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_flex/drag_target_interceptor.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_flex/drag_target_interceptor.dart index be74b4eef8..36366cd1e0 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_flex/drag_target_interceptor.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_flex/drag_target_interceptor.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import '../../utils/log.dart'; @@ -8,6 +10,8 @@ import 'reorder_flex.dart'; /// [DragTargetInterceptor] is used to intercept the [DragTarget]'s /// [onWillAccept], [OnAccept], and [onLeave] event. abstract class DragTargetInterceptor { + String get reorderFlexId; + /// Returns [yes] to receive the [DragTarget]'s event. bool canHandler(FlexDragTargetData dragTargetData); @@ -37,7 +41,7 @@ abstract class OverlapDragTargetDelegate { int dragTargetIndex, ); - bool canMoveTo(String dragTargetId); + int canMoveTo(String dragTargetId); } /// [OverlappingDragTargetInterceptor] is used to receive the overlapping @@ -47,9 +51,12 @@ abstract class OverlapDragTargetDelegate { /// Receive the [DragTarget] event if the [acceptedReorderFlexId] contains /// the passed in dragTarget' reorderFlexId. class OverlappingDragTargetInterceptor extends DragTargetInterceptor { + @override final String reorderFlexId; final List acceptedReorderFlexId; final OverlapDragTargetDelegate delegate; + final List columnKeys = []; + Timer? _delayOperation; OverlappingDragTargetInterceptor({ required this.delegate, @@ -72,15 +79,38 @@ class OverlappingDragTargetInterceptor extends DragTargetInterceptor { if (dragTargetId == dragTargetData.reorderFlexId) { delegate.cancel(); } else { - if (delegate.canMoveTo(dragTargetId)) { - delegate.moveTo(dragTargetId, dragTargetData, 0); - } + /// The priority of the column interactions is high than the cross column. + /// Workaround: delay 100 milliseconds to lower the cross column event priority. + _delayOperation?.cancel(); + _delayOperation = Timer(const Duration(milliseconds: 100), () { + final index = delegate.canMoveTo(dragTargetId); + if (index != -1) { + Log.trace( + '[$OverlappingDragTargetInterceptor] move to $dragTargetId at $index'); + delegate.moveTo(dragTargetId, dragTargetData, index); + + // final columnIndex = columnKeys + // .indexWhere((element) => element.columnId == dragTargetId); + // if (columnIndex != -1) { + // final state = columnKeys[columnIndex].key.currentState; + // if (state is ReorderFlexState) { + // state.handleOnWillAccept(context, index); + // } + // } + } + }); } return true; } } +class ColumnKey { + String columnId; + GlobalKey key; + ColumnKey({required this.columnId, required this.key}); +} + abstract class CrossReorderFlexDragTargetDelegate { /// * [reorderFlexId] is the id that the [ReorderFlex] passed in. bool acceptNewDragTargetData( @@ -96,6 +126,7 @@ abstract class CrossReorderFlexDragTargetDelegate { } class CrossReorderFlexDragTargetInterceptor extends DragTargetInterceptor { + @override final String reorderFlexId; final List acceptedReorderFlexIds; final CrossReorderFlexDragTargetDelegate delegate; @@ -119,8 +150,12 @@ class CrossReorderFlexDragTargetInterceptor extends DragTargetInterceptor { /// If the columnId equal to the dragTargetData's columnId, /// it means the dragTarget is dragging on the top of its own list. /// Otherwise, it means the dargTarget was moved to another list. + Log.trace( + "[$CrossReorderFlexDragTargetInterceptor] $reorderFlexId accept ${dragTargetData.reorderFlexId} ${reorderFlexId != dragTargetData.reorderFlexId}"); return reorderFlexId != dragTargetData.reorderFlexId; } else { + Log.trace( + "[$CrossReorderFlexDragTargetInterceptor] not accept ${dragTargetData.reorderFlexId}"); return false; } } @@ -151,6 +186,9 @@ class CrossReorderFlexDragTargetInterceptor extends DragTargetInterceptor { dragTargetIndex, ); + Log.debug( + '[$CrossReorderFlexDragTargetInterceptor] dargTargetIndex: $dragTargetIndex, reorderFlexId: $reorderFlexId'); + if (isNewDragTarget == false) { delegate.updateDragTargetData(reorderFlexId, dragTargetIndex); reorderFlexState.handleOnWillAccept(context, dragTargetIndex); diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_flex/reorder_flex.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_flex/reorder_flex.dart index 7fa1a405e1..26b68c2304 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_flex/reorder_flex.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_flex/reorder_flex.dart @@ -36,10 +36,10 @@ class ReorderFlexConfig { final double draggingWidgetOpacity = 0.3; // How long an animation to reorder an element - final Duration reorderAnimationDuration = const Duration(milliseconds: 250); + final Duration reorderAnimationDuration = const Duration(milliseconds: 300); // How long an animation to scroll to an off-screen element - final Duration scrollAnimationDuration = const Duration(milliseconds: 250); + final Duration scrollAnimationDuration = const Duration(milliseconds: 300); final bool useMoveAnimation; @@ -214,7 +214,7 @@ class ReorderFlexState extends State } Log.trace( - 'Rebuild: Column:[${dragState.id}] ${dragState.toString()}, childIndex: $childIndex shiftedIndex: $shiftedIndex'); + 'Rebuild: Column:[${dragState.reorderFlexId}] ${dragState.toString()}, childIndex: $childIndex shiftedIndex: $shiftedIndex'); final currentIndex = dragState.currentIndex; final dragPhantomIndex = dragState.phantomIndex; @@ -330,6 +330,8 @@ class ReorderFlexState extends State widget.onDragStarted?.call(draggingIndex); }, onDragEnded: (dragTargetData) { + if (!mounted) return; + Log.debug( "[DragTarget]: Column:[${widget.dataSource.identifier}] end dragging"); _notifier.updateDragTargetIndex(-1); @@ -346,21 +348,21 @@ class ReorderFlexState extends State }); }, onWillAccept: (FlexDragTargetData dragTargetData) { + // Do not receive any events if the Insert item is animating. if (_animation.deleteController.isAnimating) { return false; } assert(widget.dataSource.items.length > dragTargetIndex); - if (_interceptDragTarget( - dragTargetData, - (interceptor) => interceptor.onWillAccept( + if (_interceptDragTarget(dragTargetData, (interceptor) { + interceptor.onWillAccept( context: builderContext, reorderFlexState: this, dragTargetData: dragTargetData, dragTargetId: reorderFlexItem.id, dragTargetIndex: dragTargetIndex, - ), - )) { + ); + })) { return true; } else { return handleOnWillAccept(builderContext, dragTargetIndex); @@ -435,7 +437,7 @@ class ReorderFlexState extends State /// The [willAccept] will be true if the dargTarget is the widget that gets /// dragged and it is dragged on top of the other dragTargets. /// - Log.debug( + Log.trace( '[$ReorderDragTarget] ${widget.dataSource.identifier} on will accept, dragIndex:$dragIndex, dragTargetIndex:$dragTargetIndex, count: ${widget.dataSource.items.length}'); bool willAccept = @@ -524,7 +526,7 @@ class ReorderFlexState extends State // screen, then it is already on-screen. final double margin = widget.direction == Axis.horizontal ? dragState.dropAreaSize.width - : dragState.dropAreaSize.height; + : dragState.dropAreaSize.height / 2.0; if (_scrollController.hasClients) { final double scrollOffset = _scrollController.offset; final double topOffset = max( diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_phantom/phantom_controller.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_phantom/phantom_controller.dart index 0db70d0bae..4dd4f05a74 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_phantom/phantom_controller.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_phantom/phantom_controller.dart @@ -59,12 +59,13 @@ class BoardPhantomController extends OverlapDragTargetDelegate } void columnStartDragging(String columnId) { - columnsState.setColumnIsDragging(columnId, false); + columnsState.setColumnIsDragging(columnId, true); } /// Remove the phantom in the column when the column is end dragging. void columnEndDragging(String columnId) { - columnsState.setColumnIsDragging(columnId, true); + columnsState.setColumnIsDragging(columnId, false); + if (phantomRecord == null) return; final fromColumnId = phantomRecord!.fromColumnId; @@ -73,19 +74,18 @@ class BoardPhantomController extends OverlapDragTargetDelegate columnsState.notifyDidRemovePhantom(toColumnId); } - if (columnsState.isDragging(fromColumnId) == false) { - return; + if (phantomRecord!.toColumnId == columnId) { + delegate.swapColumnItem( + fromColumnId, + phantomRecord!.fromColumnIndex, + toColumnId, + phantomRecord!.toColumnIndex, + ); + + Log.debug( + "[$BoardPhantomController] did move ${phantomRecord.toString()}"); + phantomRecord = null; } - - delegate.swapColumnItem( - fromColumnId, - phantomRecord!.fromColumnIndex, - toColumnId, - phantomRecord!.toColumnIndex, - ); - - Log.debug("[$BoardPhantomController] did move ${phantomRecord.toString()}"); - phantomRecord = null; } /// Remove the phantom in the column if it contains phantom @@ -113,7 +113,7 @@ class BoardPhantomController extends OverlapDragTargetDelegate PhantomColumnItem(phantomContext), ); - columnsState.notifyDidInsertPhantom(toColumnId); + columnsState.notifyDidInsertPhantom(toColumnId, phantomIndex); } /// Reset or initial the [PhantomRecord] @@ -128,8 +128,9 @@ class BoardPhantomController extends OverlapDragTargetDelegate FlexDragTargetData dragTargetData, int dragTargetIndex, ) { - // Log.debug('[$BoardPhantomController] move Column:[${dragTargetData.reorderFlexId}]:${dragTargetData.draggingIndex} ' - // 'to Column:[$columnId]:$index'); + // Log.debug( + // '[$BoardPhantomController] move Column:[${dragTargetData.reorderFlexId}]:${dragTargetData.draggingIndex} ' + // 'to Column:[$columnId]:$dragTargetIndex'); phantomRecord = PhantomRecord( toColumnId: columnId, @@ -202,8 +203,17 @@ class BoardPhantomController extends OverlapDragTargetDelegate } @override - bool canMoveTo(String dragTargetId) { - return delegate.controller(dragTargetId)?.columnData.items.isEmpty ?? false; + int canMoveTo(String dragTargetId) { + if (columnsState.isDragging(dragTargetId)) { + return -1; + } + + final controller = delegate.controller(dragTargetId); + if (controller != null) { + return controller.columnData.items.length; + } else { + return 0; + } } } @@ -294,7 +304,7 @@ class PassthroughPhantomContext extends FakeDragTargetEventTrigger AFColumnItem get itemData => dragTargetData.reorderFlexItem as AFColumnItem; @override - VoidCallback? onInserted; + void Function(int?)? onInserted; @override VoidCallback? onDragEnded; @@ -308,6 +318,11 @@ class PassthroughPhantomContext extends FakeDragTargetEventTrigger void fakeOnDragEnded(VoidCallback callback) { onDragEnded = callback; } + + @override + void fakeOnDragStart(void Function(int? index) callback) { + onInserted = callback; + } } class PassthroughPhantomWidget extends PhantomWidget { diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_phantom/phantom_state.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_phantom/phantom_state.dart index d33b53500d..443d7fb936 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_phantom/phantom_state.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/reorder_phantom/phantom_state.dart @@ -14,7 +14,7 @@ class ColumnPhantomStateController { void addColumnListener(String columnId, PassthroughPhantomListener listener) { _stateWithId(columnId).notifier.addListener( - onInserted: (c) => listener.onInserted?.call(), + onInserted: (index) => listener.onInserted?.call(index), onDeleted: () => listener.onDragEnded?.call(), ); } @@ -24,8 +24,8 @@ class ColumnPhantomStateController { _states.remove(columnId); } - void notifyDidInsertPhantom(String columnId) { - _stateWithId(columnId).notifier.insert(); + void notifyDidInsertPhantom(String columnId, int index) { + _stateWithId(columnId).notifier.insert(index); } void notifyDidRemovePhantom(String columnId) { @@ -48,7 +48,7 @@ class ColumnState { } abstract class PassthroughPhantomListener { - VoidCallback? get onInserted; + void Function(int?)? get onInserted; VoidCallback? get onDragEnded; } @@ -57,8 +57,8 @@ class PassthroughPhantomNotifier { final removeNotifier = PhantomDeleteNotifier(); - void insert() { - insertNotifier.insert(); + void insert(int index) { + insertNotifier.insert(index); } void remove() { @@ -66,12 +66,12 @@ class PassthroughPhantomNotifier { } void addListener({ - void Function(PassthroughPhantomContext? insertedPhantom)? onInserted, + void Function(int? insertedIndex)? onInserted, void Function()? onDeleted, }) { if (onInserted != null) { insertNotifier.addListener(() { - onInserted(insertNotifier.insertedPhantom); + onInserted(insertNotifier.insertedIndex); }); } @@ -89,9 +89,11 @@ class PassthroughPhantomNotifier { } class PhantomInsertNotifier extends ChangeNotifier { + int insertedIndex = -1; PassthroughPhantomContext? insertedPhantom; - void insert() { + void insert(int index) { + insertedIndex = index; notifyListeners(); } } diff --git a/frontend/app_flowy/packages/appflowy_board/pubspec.yaml b/frontend/app_flowy/packages/appflowy_board/pubspec.yaml index 962fc8be80..6bb2feabfe 100644 --- a/frontend/app_flowy/packages/appflowy_board/pubspec.yaml +++ b/frontend/app_flowy/packages/appflowy_board/pubspec.yaml @@ -1,6 +1,6 @@ name: appflowy_board description: AppFlowy board implementation. -version: 0.0.4 +version: 0.0.5 homepage: https://github.com/AppFlowy-IO/AppFlowy repository: https://github.com/AppFlowy-IO/AppFlowy/tree/main/frontend/app_flowy/packages/appflowy_board