diff --git a/frontend/app_flowy/packages/flowy_board/lib/flowy_board.dart b/frontend/app_flowy/packages/flowy_board/lib/flowy_board.dart index 0611432b4a..16d2c612d3 100644 --- a/frontend/app_flowy/packages/flowy_board/lib/flowy_board.dart +++ b/frontend/app_flowy/packages/flowy_board/lib/flowy_board.dart @@ -3,3 +3,4 @@ library flowy_board; export 'src/widgets/board_column/board_column.dart'; export 'src/widgets/board_column/data_controller.dart'; export 'src/widgets/board.dart'; +export 'src/widgets/board_data.dart'; diff --git a/frontend/app_flowy/packages/flowy_board/lib/src/widgets/board.dart b/frontend/app_flowy/packages/flowy_board/lib/src/widgets/board.dart index 2a49de26ba..f425bcd556 100644 --- a/frontend/app_flowy/packages/flowy_board/lib/src/widgets/board.dart +++ b/frontend/app_flowy/packages/flowy_board/lib/src/widgets/board.dart @@ -1,13 +1,10 @@ -import 'dart:collection'; -import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import '../../flowy_board.dart'; - -import '../rendering/board_overlay.dart'; import 'flex/drag_target_inteceptor.dart'; import 'flex/reorder_flex.dart'; import 'phantom/phantom_controller.dart'; +import '../../flowy_board.dart'; +import '../rendering/board_overlay.dart'; class Board extends StatelessWidget { /// The direction to use as the main axis. @@ -60,54 +57,17 @@ class Board extends StatelessWidget { value: dataController, child: Consumer( builder: (context, notifier, child) { - List children = dataController.columnDatas.map((columnData) { - final controller = dataController.columnController(columnData.id); - - return _buildColumn( - columnData.id, - dataController.columnIds, - controller, - ); - }).toList(); - - return BoardColumnContainer( - onReorder: dataController.onReorder, - boardDataController: dataController, + return BoardContent( + dataController: dataController, background: background, spacing: spacing, delegate: phantomController, - children: children, - ); - }, - ), - ); - } - - /// - Widget _buildColumn( - String columnId, - List acceptColumns, - BoardColumnDataController dataController, - ) { - return ChangeNotifierProvider.value( - key: ValueKey(columnId), - value: dataController, - child: Consumer( - builder: (context, value, child) { - return ConstrainedBox( - constraints: columnConstraints, - child: BoardColumnWidget( - headerBuilder: headerBuilder, - footBuilder: footBuilder, - cardBuilder: cardBuilder, - acceptedColumns: acceptColumns, - dataController: dataController, - scrollController: ScrollController(), - onReorder: (_, int fromIndex, int toIndex) { - dataController.move(fromIndex, toIndex); - }, - phantomController: phantomController, - ), + columnConstraints: columnConstraints, + cardBuilder: cardBuilder, + footBuilder: footBuilder, + headerBuilder: headerBuilder, + phantomController: phantomController, + onReorder: dataController.onReorder, ); }, ), @@ -115,96 +75,73 @@ class Board extends StatelessWidget { } } -class BoardDataController extends ChangeNotifier - with EquatableMixin, BoardPhantomControllerDelegate, ReoderFlextDataSource { - final List _columnDatas = []; - - List get columnDatas => _columnDatas; - - List get columnIds => - _columnDatas.map((columnData) => columnData.id).toList(); - - final LinkedHashMap _columnControllers = - LinkedHashMap(); - - BoardDataController(); - - void setColumnData(BoardColumnData columnData) { - final controller = BoardColumnDataController(columnData: columnData); - _columnDatas.add(columnData); - _columnControllers[columnData.id] = controller; - } - - BoardColumnDataController columnController(String columnId) { - return _columnControllers[columnId]!; - } - - void onReorder(int fromIndex, int toIndex) { - final columnData = _columnDatas.removeAt(fromIndex); - _columnDatas.insert(toIndex, columnData); - notifyListeners(); - } - - @override - List get props { - return [_columnDatas]; - } - - @override - BoardColumnDataController? controller(String columnId) { - return _columnControllers[columnId]; - } - - @override - String get identifier => '$BoardDataController'; - - @override - List get items => _columnDatas; -} - -class BoardColumnContainer extends StatefulWidget { +class BoardContent extends StatefulWidget { final ScrollController? scrollController; final OnDragStarted? onDragStarted; final OnReorder onReorder; final OnDragEnded? onDragEnded; - final BoardDataController boardDataController; - final List children; + final BoardDataController dataController; final Widget? background; final double spacing; final ReorderFlexConfig config; + final BoxConstraints columnConstraints; + + /// + final BoardColumnCardBuilder cardBuilder; + + /// + final BoardColumnHeaderBuilder? headerBuilder; + + /// + final BoardColumnFooterBuilder? footBuilder; final OverlapReorderFlexDragTargetDelegate delegate; - const BoardColumnContainer({ + final BoardPhantomController phantomController; + + const BoardContent({ required this.onReorder, - required this.children, required this.delegate, - required this.boardDataController, + required this.dataController, this.onDragStarted, this.onDragEnded, this.scrollController, this.background, this.spacing = 0.0, this.config = const ReorderFlexConfig(), + required this.columnConstraints, + required this.cardBuilder, + this.footBuilder, + this.headerBuilder, + required this.phantomController, Key? key, }) : super(key: key); @override - State createState() => _BoardColumnContainerState(); + State createState() => _BoardContentState(); } -class _BoardColumnContainerState extends State { +class _BoardContentState extends State { final GlobalKey _columnContainerOverlayKey = - GlobalKey(debugLabel: '$BoardColumnContainer overlay key'); + GlobalKey(debugLabel: '$BoardContent overlay key'); late BoardOverlayEntry _overlayEntry; @override void initState() { _overlayEntry = BoardOverlayEntry( builder: (BuildContext context) { + List children = + widget.dataController.columnDatas.map((columnData) { + return _buildColumn( + columnData.id, + widget.dataController.columnIds, + widget.dataController.columnController(columnData.id), + ); + }).toList(); + final interceptor = OverlapReorderFlexDragTargetInteceptor( - reorderFlexId: widget.boardDataController.identifier, - acceptedReorderFlexId: widget.boardDataController.columnIds, + reorderFlexId: widget.dataController.identifier, + acceptedReorderFlexId: widget.dataController.columnIds, delegate: widget.delegate, ); @@ -215,14 +152,20 @@ class _BoardColumnContainerState extends State { onDragStarted: widget.onDragStarted, onReorder: widget.onReorder, onDragEnded: widget.onDragEnded, - dataSource: widget.boardDataController, + dataSource: widget.dataController, direction: Axis.horizontal, spacing: widget.spacing, interceptor: interceptor, - children: widget.children, + children: children, ); - return _wrapStack(reorderFlex); + return Stack( + alignment: AlignmentDirectional.topStart, + children: [ + if (widget.background != null) widget.background!, + reorderFlex, + ], + ); }, opaque: false, ); @@ -237,13 +180,33 @@ class _BoardColumnContainerState extends State { ); } - Widget _wrapStack(Widget child) { - return Stack( - alignment: AlignmentDirectional.topStart, - children: [ - if (widget.background != null) widget.background!, - child, - ], + Widget _buildColumn( + String columnId, + List acceptColumns, + BoardColumnDataController dataController, + ) { + return ChangeNotifierProvider.value( + key: ValueKey(columnId), + value: dataController, + child: Consumer( + builder: (context, value, child) { + return ConstrainedBox( + constraints: widget.columnConstraints, + child: BoardColumnWidget( + headerBuilder: widget.headerBuilder, + footBuilder: widget.footBuilder, + cardBuilder: widget.cardBuilder, + acceptedColumns: acceptColumns, + dataController: dataController, + scrollController: ScrollController(), + onReorder: (_, int fromIndex, int toIndex) { + dataController.move(fromIndex, toIndex); + }, + phantomController: widget.phantomController, + ), + ); + }, + ), ); } } diff --git a/frontend/app_flowy/packages/flowy_board/lib/src/widgets/board_data.dart b/frontend/app_flowy/packages/flowy_board/lib/src/widgets/board_data.dart new file mode 100644 index 0000000000..818258ed71 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_board/lib/src/widgets/board_data.dart @@ -0,0 +1,55 @@ +import 'dart:collection'; + +import 'package:equatable/equatable.dart'; + +import '../../flowy_board.dart'; +import 'flex/reorder_flex.dart'; +import 'package:flutter/material.dart'; +import 'phantom/phantom_controller.dart'; + +class BoardDataController extends ChangeNotifier + with EquatableMixin, BoardPhantomControllerDelegate, ReoderFlextDataSource { + final List _columnDatas = []; + + List get columnDatas => _columnDatas; + + List get columnIds => + _columnDatas.map((columnData) => columnData.id).toList(); + + final LinkedHashMap _columnControllers = + LinkedHashMap(); + + BoardDataController(); + + void setColumnData(BoardColumnData columnData) { + final controller = BoardColumnDataController(columnData: columnData); + _columnDatas.add(columnData); + _columnControllers[columnData.id] = controller; + } + + BoardColumnDataController columnController(String columnId) { + return _columnControllers[columnId]!; + } + + void onReorder(int fromIndex, int toIndex) { + final columnData = _columnDatas.removeAt(fromIndex); + _columnDatas.insert(toIndex, columnData); + notifyListeners(); + } + + @override + List get props { + return [_columnDatas]; + } + + @override + BoardColumnDataController? controller(String columnId) { + return _columnControllers[columnId]; + } + + @override + String get identifier => '$BoardDataController'; + + @override + List get items => _columnDatas; +} diff --git a/frontend/app_flowy/packages/flowy_board/lib/src/widgets/flex/drag_target_inteceptor.dart b/frontend/app_flowy/packages/flowy_board/lib/src/widgets/flex/drag_target_inteceptor.dart index 4e551c057c..09a8e2b064 100644 --- a/frontend/app_flowy/packages/flowy_board/lib/src/widgets/flex/drag_target_inteceptor.dart +++ b/frontend/app_flowy/packages/flowy_board/lib/src/widgets/flex/drag_target_inteceptor.dart @@ -16,15 +16,14 @@ abstract class ReorderFlexDragTargetInterceptor { required int dragTargetIndex, }); - void onAccept(FlexDragTargetData dragTargetData); + void onAccept(FlexDragTargetData dragTargetData) {} - void onLeave(FlexDragTargetData dragTargetData); + void onLeave(FlexDragTargetData dragTargetData) {} - ReorderFlexDraggableTargetBuilder? get draggableTargetBuilder; + ReorderFlexDraggableTargetBuilder? get draggableTargetBuilder => null; } -abstract class OverlapReorderFlexDragTargetDelegate - extends CrossReorderFlexDragTargetDelegate {} +abstract class OverlapReorderFlexDragTargetDelegate {} class OverlapReorderFlexDragTargetInteceptor extends ReorderFlexDragTargetInterceptor { @@ -43,15 +42,6 @@ class OverlapReorderFlexDragTargetInteceptor return acceptedReorderFlexId.contains(dragTargetData.reorderFlexId); } - @override - ReorderFlexDraggableTargetBuilder? get draggableTargetBuilder => null; - - @override - void onAccept(FlexDragTargetData dragTargetData) {} - - @override - void onLeave(FlexDragTargetData dragTargetData) {} - @override bool onWillAccept( {required BuildContext context, @@ -59,10 +49,9 @@ class OverlapReorderFlexDragTargetInteceptor required FlexDragTargetData dragTargetData, required String dragTargetId, required int dragTargetIndex}) { - Log.trace('dragTargetData: $dragTargetData'); - Log.trace('currentDragTargetId: $dragTargetId'); - // - Log.debug('Switch to $dragTargetId'); + if (dragTargetId == dragTargetData.reorderFlexId) { + Log.debug('remove all phantom'); + } return true; } @@ -70,12 +59,13 @@ class OverlapReorderFlexDragTargetInteceptor abstract class CrossReorderFlexDragTargetDelegate { bool acceptNewDragTargetData( - String columnId, + String reorderFlexId, FlexDragTargetData dragTargetData, int index, ); + void updateDragTargetData( - String columnId, + String reorderFlexId, FlexDragTargetData dragTargetData, int index, ); @@ -149,10 +139,6 @@ class CrossReorderFlexDragTargetInterceptor dragTargetData.draggingIndex, dragTargetIndex, ); - } else { - Log.debug( - '[$CrossReorderFlexDragTargetInterceptor] move Column${dragTargetData.reorderFlexId}:${dragTargetData.draggingIndex} ' - 'to Column$reorderFlexId:$dragTargetIndex'); } return true; diff --git a/frontend/app_flowy/packages/flowy_board/lib/src/widgets/flex/reorder_flex.dart b/frontend/app_flowy/packages/flowy_board/lib/src/widgets/flex/reorder_flex.dart index 9ed78dcdb1..b1d3c59a9f 100644 --- a/frontend/app_flowy/packages/flowy_board/lib/src/widgets/flex/reorder_flex.dart +++ b/frontend/app_flowy/packages/flowy_board/lib/src/widgets/flex/reorder_flex.dart @@ -317,7 +317,8 @@ class ReorderFlexState extends State }, onWillAccept: (FlexDragTargetData dragTargetData) { assert(widget.dataSource.items.length > dragTargetIndex); - + Log.debug( + '[$ReorderDragTarget] ${widget.dataSource.identifier} on will accept, count: ${widget.dataSource.items.length}'); if (_interceptDragTarget( dragTargetData, (interceptor) => interceptor.onWillAccept( @@ -330,8 +331,6 @@ class ReorderFlexState extends State )) { return true; } else { - Log.debug( - '[$ReorderDragTarget] ${widget.dataSource.identifier} on will accept, count: ${widget.dataSource.items.length}'); final dragIndex = dragTargetData.draggingIndex; return onWillAccept(builderContext, dragIndex, dragTargetIndex); } diff --git a/frontend/app_flowy/packages/flowy_board/lib/src/widgets/phantom/phantom_controller.dart b/frontend/app_flowy/packages/flowy_board/lib/src/widgets/phantom/phantom_controller.dart index 005169278a..65c3cfbe16 100644 --- a/frontend/app_flowy/packages/flowy_board/lib/src/widgets/phantom/phantom_controller.dart +++ b/frontend/app_flowy/packages/flowy_board/lib/src/widgets/phantom/phantom_controller.dart @@ -14,10 +14,8 @@ mixin ColumnDataPhantomMixim { BoardColumnDataController? get; } -class BoardPhantomController - with - CrossReorderFlexDragTargetDelegate, - OverlapReorderFlexDragTargetDelegate { +class BoardPhantomController extends OverlapReorderFlexDragTargetDelegate + with CrossReorderFlexDragTargetDelegate { final BoardPhantomControllerDelegate delegate; PhantomRecord? phantomRecord; @@ -85,43 +83,6 @@ class BoardPhantomController phantomRecord = null; } - @override - bool acceptNewDragTargetData( - String columnId, FlexDragTargetData dragTargetData, int index) { - if (phantomRecord == null) { - _updatePhantomRecord(columnId, dragTargetData, index); - _insertPhantom(columnId, dragTargetData, index); - - return true; - } - - final isDifferentDragTarget = phantomRecord!.toColumnId != columnId; - Log.debug( - '[$BoardPhantomController] Set inserted column id: $columnId, different target: $isDifferentDragTarget'); - if (isDifferentDragTarget) { - /// Remove the phantom in the previous column. - _removePhantom(phantomRecord!.toColumnId); - - /// Update the record and insert the phantom to new column. - _updatePhantomRecord(columnId, dragTargetData, index); - _insertPhantom(columnId, dragTargetData, index); - } - - return isDifferentDragTarget; - } - - @override - void updateDragTargetData( - String columnId, FlexDragTargetData dragTargetData, int index) { - phantomRecord?.updateInsertedIndex(index); - - assert(phantomRecord != null); - if (phantomRecord!.toColumnId == columnId) { - /// Update the existing phantom index - _updatePhantom(phantomRecord!.toColumnId, dragTargetData, index); - } - } - void _updatePhantom( String toColumnId, FlexDragTargetData dragTargetData, @@ -197,6 +158,10 @@ class BoardPhantomController FlexDragTargetData dragTargetData, int index, ) { + Log.debug( + '[$BoardPhantomController] move Column${dragTargetData.reorderFlexId}:${dragTargetData.draggingIndex} ' + 'to Column$columnId:$index'); + phantomRecord = PhantomRecord( toColumnId: columnId, toColumnIndex: index, @@ -205,6 +170,42 @@ class BoardPhantomController fromColumnIndex: dragTargetData.draggingIndex, ); } + + @override + bool acceptNewDragTargetData( + String reorderFlexId, FlexDragTargetData dragTargetData, int index) { + if (phantomRecord == null) { + _updatePhantomRecord(reorderFlexId, dragTargetData, index); + _insertPhantom(reorderFlexId, dragTargetData, index); + return false; + } + + final isNewDragTarget = phantomRecord!.toColumnId != reorderFlexId; + Log.debug( + '[$BoardPhantomController] Set inserted column id: $reorderFlexId, is new target: $isNewDragTarget'); + if (isNewDragTarget) { + /// Remove the phantom in the previous column. + _removePhantom(phantomRecord!.toColumnId); + + /// Update the record and insert the phantom to new column. + _updatePhantomRecord(reorderFlexId, dragTargetData, index); + _insertPhantom(reorderFlexId, dragTargetData, index); + } + + return isNewDragTarget; + } + + @override + void updateDragTargetData( + String reorderFlexId, FlexDragTargetData dragTargetData, int index) { + phantomRecord?.updateInsertedIndex(index); + + assert(phantomRecord != null); + if (phantomRecord!.toColumnId == reorderFlexId) { + /// Update the existing phantom index + _updatePhantom(phantomRecord!.toColumnId, dragTargetData, index); + } + } } class PhantomRecord { @@ -234,6 +235,8 @@ class PhantomRecord { void updateInsertedIndex(int index) { if (toColumnIndex == index) { + Log.info( + '[$PhantomRecord] Column$toColumnId toColumnIndex: $toColumnIndex, index: $index'); return; }