From c7fdfb40909d04edc5197af4237aedfe0ec27ca7 Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 5 Sep 2022 16:29:16 +0800 Subject: [PATCH 1/4] chore: update documentation --- .../plugins/board/application/board_bloc.dart | 50 ++-- .../board/presentation/board_page.dart | 28 +-- .../packages/appflowy_board/README.md | 14 +- .../example/lib/multi_board_list_example.dart | 62 ++--- .../lib/single_board_list_example.dart | 10 +- .../appflowy_board/lib/src/widgets/board.dart | 213 ++++++++++-------- .../widgets/board_column/board_column.dart | 109 ++++----- .../board_column/board_column_data.dart | 119 +++++----- .../lib/src/widgets/board_data.dart | 198 ++++++++-------- .../reorder_flex/drag_target_interceptor.dart | 10 +- .../widgets/reorder_flex/reorder_flex.dart | 10 +- .../reorder_phantom/phantom_controller.dart | 173 +++++++------- .../reorder_phantom/phantom_state.dart | 40 ++-- .../lib/src/widgets/styled_widgets/card.dart | 8 +- .../src/widgets/styled_widgets/footer.dart | 8 +- .../src/widgets/styled_widgets/header.dart | 8 +- 16 files changed, 545 insertions(+), 515 deletions(-) diff --git a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart index 11f4cf6910..faf3490b70 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart @@ -22,7 +22,7 @@ part 'board_bloc.freezed.dart'; class BoardBloc extends Bloc { final BoardDataController _gridDataController; - late final AFBoardDataController boardController; + late final AppFlowyBoardDataController boardController; final MoveRowFFIService _rowService; LinkedHashMap groupControllers = LinkedHashMap(); @@ -34,8 +34,8 @@ class BoardBloc extends Bloc { : _rowService = MoveRowFFIService(gridId: view.id), _gridDataController = BoardDataController(view: view), super(BoardState.initial(view.id)) { - boardController = AFBoardDataController( - onMoveColumn: ( + boardController = AppFlowyBoardDataController( + onMoveGroup: ( fromColumnId, fromIndex, toColumnId, @@ -43,7 +43,7 @@ class BoardBloc extends Bloc { ) { _moveGroup(fromColumnId, toColumnId); }, - onMoveColumnItem: ( + onMoveGroupItem: ( columnId, fromIndex, toIndex, @@ -52,15 +52,15 @@ class BoardBloc extends Bloc { final toRow = groupControllers[columnId]?.rowAtIndex(toIndex); _moveRow(fromRow, columnId, toRow); }, - onMoveColumnItemToColumn: ( - fromColumnId, + onMoveGroupItemToGroup: ( + fromGroupId, fromIndex, - toColumnId, + toGroupId, toIndex, ) { - final fromRow = groupControllers[fromColumnId]?.rowAtIndex(fromIndex); - final toRow = groupControllers[toColumnId]?.rowAtIndex(toIndex); - _moveRow(fromRow, toColumnId, toRow); + final fromRow = groupControllers[fromGroupId]?.rowAtIndex(fromIndex); + final toRow = groupControllers[toGroupId]?.rowAtIndex(toIndex); + _moveRow(fromRow, toGroupId, toRow); }, ); @@ -165,10 +165,10 @@ class BoardBloc extends Bloc { boardController.clear(); // - List columns = groups + List columns = groups .where((group) => fieldController.getField(group.fieldId) != null) .map((group) { - return AFBoardColumnData( + return AppFlowyBoardGroupData( id: group.groupId, name: group.desc, items: _buildRows(group), @@ -178,7 +178,7 @@ class BoardBloc extends Bloc { ), ); }).toList(); - boardController.addColumns(columns); + boardController.addGroups(columns); for (final group in groups) { final delegate = GroupControllerDelegateImpl( @@ -227,8 +227,8 @@ class BoardBloc extends Bloc { if (isClosed) return; for (final group in updatedGroups) { final columnController = - boardController.getColumnController(group.groupId); - columnController?.updateColumnName(group.desc); + boardController.getGroupController(group.groupId); + columnController?.updateGroupName(group.desc); } }, onError: (err) { @@ -243,13 +243,13 @@ class BoardBloc extends Bloc { ); } - List _buildRows(GroupPB group) { + List _buildRows(GroupPB group) { final items = group.rows.map((row) { final fieldContext = fieldController.getField(group.fieldId); return BoardColumnItem(row: row, fieldContext: fieldContext!); }).toList(); - return [...items]; + return [...items]; } Future _loadGrid(Emitter emit) async { @@ -335,7 +335,7 @@ class GridFieldEquatable extends Equatable { UnmodifiableListView get value => UnmodifiableListView(_fields); } -class BoardColumnItem extends AFColumnItem { +class BoardColumnItem extends AppFlowyGroupItem { final RowPB row; final GridFieldContext fieldContext; @@ -350,7 +350,7 @@ class BoardColumnItem extends AFColumnItem { class GroupControllerDelegateImpl extends GroupControllerDelegate { final GridFieldController fieldController; - final AFBoardDataController controller; + final AppFlowyBoardDataController controller; final void Function(String, RowPB, int?) onNewColumnItem; GroupControllerDelegateImpl({ @@ -369,16 +369,16 @@ class GroupControllerDelegateImpl extends GroupControllerDelegate { if (index != null) { final item = BoardColumnItem(row: row, fieldContext: fieldContext); - controller.insertColumnItem(group.groupId, index, item); + controller.insertGroupItem(group.groupId, index, item); } else { final item = BoardColumnItem(row: row, fieldContext: fieldContext); - controller.addColumnItem(group.groupId, item); + controller.addGroupItem(group.groupId, item); } } @override void removeRow(GroupPB group, String rowId) { - controller.removeColumnItem(group.groupId, rowId); + controller.removeGroupItem(group.groupId, rowId); } @override @@ -388,7 +388,7 @@ class GroupControllerDelegateImpl extends GroupControllerDelegate { Log.warn("FieldContext should not be null"); return; } - controller.updateColumnItem( + controller.updateGroupItem( group.groupId, BoardColumnItem(row: row, fieldContext: fieldContext), ); @@ -404,9 +404,9 @@ class GroupControllerDelegateImpl extends GroupControllerDelegate { final item = BoardColumnItem(row: row, fieldContext: fieldContext); if (index != null) { - controller.insertColumnItem(group.groupId, index, item); + controller.insertGroupItem(group.groupId, index, item); } else { - controller.addColumnItem(group.groupId, item); + controller.addGroupItem(group.groupId, item); } onNewColumnItem(group.groupId, row, index); } diff --git a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart index 233917ec8c..35f50dd121 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart @@ -65,8 +65,8 @@ class _BoardContentState extends State { late ScrollController scrollController; late AFBoardScrollManager scrollManager; - final config = AFBoardConfig( - columnBackgroundColor: HexColor.fromHex('#F7F8FC'), + final config = AppFlowyBoardConfig( + groupBackgroundColor: HexColor.fromHex('#F7F8FC'), ); @override @@ -101,7 +101,7 @@ class _BoardContentState extends State { Expanded _buildBoard(BuildContext context) { return Expanded( - child: AFBoard( + child: AppFlowyBoard( scrollManager: scrollManager, scrollController: scrollController, dataController: context.read().boardController, @@ -112,9 +112,9 @@ class _BoardContentState extends State { column, columnItem, ), - columnConstraints: const BoxConstraints.tightFor(width: 300), - config: AFBoardConfig( - columnBackgroundColor: HexColor.fromHex('#F7F8FC'), + groupConstraints: const BoxConstraints.tightFor(width: 300), + config: AppFlowyBoardConfig( + groupBackgroundColor: HexColor.fromHex('#F7F8FC'), ), ), ); @@ -149,14 +149,14 @@ class _BoardContentState extends State { Widget _buildHeader( BuildContext context, - AFBoardColumnData columnData, + AppFlowyBoardGroupData columnData, ) { final boardCustomData = columnData.customData as BoardCustomData; - return AppFlowyColumnHeader( + return AppFlowyGroupHeader( title: Flexible( fit: FlexFit.tight, child: FlowyText.medium( - columnData.headerData.columnName, + columnData.headerData.groupName, fontSize: 14, overflow: TextOverflow.clip, color: context.read().textColor, @@ -181,14 +181,14 @@ class _BoardContentState extends State { ); } - Widget _buildFooter(BuildContext context, AFBoardColumnData columnData) { + Widget _buildFooter(BuildContext context, AppFlowyBoardGroupData columnData) { final boardCustomData = columnData.customData as BoardCustomData; final group = boardCustomData.group; if (group.isDefault) { return const SizedBox(); } else { - return AppFlowyColumnFooter( + return AppFlowyGroupFooter( icon: SizedBox( height: 20, width: 20, @@ -215,8 +215,8 @@ class _BoardContentState extends State { Widget _buildCard( BuildContext context, - AFBoardColumnData column, - AFColumnItem columnItem, + AppFlowyBoardGroupData column, + AppFlowyGroupItem columnItem, ) { final boardColumnItem = columnItem as BoardColumnItem; final rowPB = boardColumnItem.row; @@ -242,7 +242,7 @@ class _BoardContentState extends State { }, ); - return AppFlowyColumnItemCard( + return AppFlowyGroupItemCard( key: ValueKey(columnItem.id), margin: config.cardPadding, decoration: _makeBoxDecoration(context), diff --git a/frontend/app_flowy/packages/appflowy_board/README.md b/frontend/app_flowy/packages/appflowy_board/README.md index 8da1064699..7360bde69d 100644 --- a/frontend/app_flowy/packages/appflowy_board/README.md +++ b/frontend/app_flowy/packages/appflowy_board/README.md @@ -9,6 +9,7 @@ Twitter

+

@@ -30,6 +31,7 @@ Add the AppFlowy Board [Flutter package](https://docs.flutter.dev/development/pa With Flutter: ```dart flutter pub add appflowy_board +flutter pub get ``` This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get): @@ -38,6 +40,8 @@ dependencies: appflowy_board: ^0.0.6 ``` +## Create board + Import the package in your Dart file: ```dart import 'package:appflowy_board/appflowy_board.dart'; @@ -47,14 +51,18 @@ import 'package:appflowy_board/appflowy_board.dart'; To quickly grasp how it can be used, look at the /example/lib folder. First, run main.dart to play with the demo. + Second, let's delve into multi_board_list_example.dart to understand a few key components: * A Board widget is created via instantiating an AFBoard() object. * In the AFBoard() object, you can find: * AFBoardDataController, which is defined in board_data.dart, is feeded with prepopulated mock data. It also contains callback functions to materialize future user data. * Three builders: AppFlowyColumnHeader, AppFlowyColumnFooter, AppFlowyColumnItemCard. See below image for what they are used for. -

+ + + + ## Glossary Please refer to the API documentation. @@ -68,4 +76,4 @@ Please look at [CONTRIBUTING.md](https://appflowy.gitbook.io/docs/essential-docu Distributed under the AGPLv3 License. See [LICENSE](https://github.com/AppFlowy-IO/AppFlowy-Docs/blob/main/LICENSE) for more information. - +d \ No newline at end of file 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 c0fc62f8e2..18f5118ced 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 @@ -9,21 +9,22 @@ class MultiBoardListExample extends StatefulWidget { } class _MultiBoardListExampleState extends State { - final AFBoardDataController boardDataController = AFBoardDataController( - onMoveColumn: (fromColumnId, fromIndex, toColumnId, toIndex) { + final AppFlowyBoardDataController boardDataController = + AppFlowyBoardDataController( + onMoveGroup: (fromColumnId, fromIndex, toColumnId, toIndex) { // debugPrint('Move column from $fromIndex to $toIndex'); }, - onMoveColumnItem: (columnId, fromIndex, toIndex) { + onMoveGroupItem: (columnId, fromIndex, toIndex) { // debugPrint('Move $columnId:$fromIndex to $columnId:$toIndex'); }, - onMoveColumnItemToColumn: (fromColumnId, fromIndex, toColumnId, toIndex) { + onMoveGroupItemToGroup: (fromColumnId, fromIndex, toColumnId, toIndex) { // debugPrint('Move $fromColumnId:$fromIndex to $toColumnId:$toIndex'); }, ); @override void initState() { - List a = [ + List a = [ TextItem("Card 1"), TextItem("Card 2"), RichTextItem(title: "Card 3", subtitle: 'Aug 1, 2020 4:05 PM'), @@ -35,82 +36,83 @@ class _MultiBoardListExampleState extends State { TextItem("Card 9"), ]; - final column1 = AFBoardColumnData(id: "To Do", name: "To Do", items: a); - final column2 = AFBoardColumnData( + final column1 = + AppFlowyBoardGroupData(id: "To Do", name: "To Do", items: a); + final column2 = AppFlowyBoardGroupData( id: "In Progress", name: "In Progress", - items: [ + items: [ RichTextItem(title: "Card 10", subtitle: 'Aug 1, 2020 4:05 PM'), TextItem("Card 11"), ], ); - final column3 = - AFBoardColumnData(id: "Done", name: "Done", items: []); + final column3 = AppFlowyBoardGroupData( + id: "Done", name: "Done", items: []); - boardDataController.addColumn(column1); - boardDataController.addColumn(column2); - boardDataController.addColumn(column3); + boardDataController.addGroup(column1); + boardDataController.addGroup(column2); + boardDataController.addGroup(column3); super.initState(); } @override Widget build(BuildContext context) { - final config = AFBoardConfig( - columnBackgroundColor: HexColor.fromHex('#F7F8FC'), + final config = AppFlowyBoardConfig( + groupBackgroundColor: HexColor.fromHex('#F7F8FC'), ); return Container( color: Colors.white, child: Padding( padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 20), - child: AFBoard( + child: AppFlowyBoard( dataController: boardDataController, footerBuilder: (context, columnData) { - return AppFlowyColumnFooter( + return AppFlowyGroupFooter( icon: const Icon(Icons.add, size: 20), title: const Text('New'), height: 50, - margin: config.columnItemPadding, + margin: config.groupItemPadding, ); }, headerBuilder: (context, columnData) { - return AppFlowyColumnHeader( + return AppFlowyGroupHeader( icon: const Icon(Icons.lightbulb_circle), title: SizedBox( width: 60, child: TextField( controller: TextEditingController() - ..text = columnData.headerData.columnName, + ..text = columnData.headerData.groupName, onSubmitted: (val) { boardDataController - .getColumnController(columnData.headerData.columnId)! - .updateColumnName(val); + .getGroupController(columnData.headerData.groupId)! + .updateGroupName(val); }, ), ), addIcon: const Icon(Icons.add, size: 20), moreIcon: const Icon(Icons.more_horiz, size: 20), height: 50, - margin: config.columnItemPadding, + margin: config.groupItemPadding, ); }, cardBuilder: (context, column, columnItem) { - return AppFlowyColumnItemCard( + return AppFlowyGroupItemCard( key: ValueKey(columnItem.id), child: _buildCard(columnItem), ); }, - columnConstraints: const BoxConstraints.tightFor(width: 240), - config: AFBoardConfig( - columnBackgroundColor: HexColor.fromHex('#F7F8FC'), + groupConstraints: const BoxConstraints.tightFor(width: 240), + config: AppFlowyBoardConfig( + groupBackgroundColor: HexColor.fromHex('#F7F8FC'), ), ), ), ); } - Widget _buildCard(AFColumnItem item) { + Widget _buildCard(AppFlowyGroupItem item) { if (item is TextItem) { return Align( alignment: Alignment.centerLeft, @@ -172,7 +174,7 @@ class _RichTextCardState extends State { } } -class TextItem extends AFColumnItem { +class TextItem extends AppFlowyGroupItem { final String s; TextItem(this.s); @@ -181,7 +183,7 @@ class TextItem extends AFColumnItem { String get id => s; } -class RichTextItem extends AFColumnItem { +class RichTextItem extends AppFlowyGroupItem { final String title; final String subtitle; diff --git a/frontend/app_flowy/packages/appflowy_board/example/lib/single_board_list_example.dart b/frontend/app_flowy/packages/appflowy_board/example/lib/single_board_list_example.dart index f22c562343..5c68a24e62 100644 --- a/frontend/app_flowy/packages/appflowy_board/example/lib/single_board_list_example.dart +++ b/frontend/app_flowy/packages/appflowy_board/example/lib/single_board_list_example.dart @@ -9,11 +9,11 @@ class SingleBoardListExample extends StatefulWidget { } class _SingleBoardListExampleState extends State { - final AFBoardDataController boardData = AFBoardDataController(); + final AppFlowyBoardDataController boardData = AppFlowyBoardDataController(); @override void initState() { - final column = AFBoardColumnData( + final column = AppFlowyBoardGroupData( id: "1", name: "1", items: [ @@ -24,13 +24,13 @@ class _SingleBoardListExampleState extends State { ], ); - boardData.addColumn(column); + boardData.addGroup(column); super.initState(); } @override Widget build(BuildContext context) { - return AFBoard( + return AppFlowyBoard( dataController: boardData, cardBuilder: (context, column, columnItem) { return _RowWidget( @@ -55,7 +55,7 @@ class _RowWidget extends StatelessWidget { } } -class TextItem extends AFColumnItem { +class TextItem extends AppFlowyGroupItem { final String s; TextItem(this.s); 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 96874a1425..7ed69db822 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 @@ -11,70 +11,78 @@ import 'reorder_phantom/phantom_controller.dart'; import '../rendering/board_overlay.dart'; class AFBoardScrollManager { - BoardColumnsState? _columnState; + BoardGroupsState? _groupState; - // AFBoardScrollManager(); - - void scrollToBottom(String columnId, VoidCallback? completed) { - _columnState - ?.getReorderFlexState(columnId: columnId) + void scrollToBottom(String groupId, VoidCallback? completed) { + _groupState + ?.getReorderFlexState(groupId: groupId) ?.scrollToBottom(completed); } } -class AFBoardConfig { +class AppFlowyBoardConfig { final double cornerRadius; - final EdgeInsets columnPadding; - final EdgeInsets columnItemPadding; + final EdgeInsets groupPadding; + final EdgeInsets groupItemPadding; final EdgeInsets footerPadding; final EdgeInsets headerPadding; final EdgeInsets cardPadding; - final Color columnBackgroundColor; + final Color groupBackgroundColor; - const AFBoardConfig({ + const AppFlowyBoardConfig({ this.cornerRadius = 6.0, - this.columnPadding = const EdgeInsets.symmetric(horizontal: 8), - this.columnItemPadding = const EdgeInsets.symmetric(horizontal: 12), + this.groupPadding = const EdgeInsets.symmetric(horizontal: 8), + this.groupItemPadding = const EdgeInsets.symmetric(horizontal: 12), this.footerPadding = const EdgeInsets.symmetric(horizontal: 12), this.headerPadding = const EdgeInsets.symmetric(horizontal: 16), this.cardPadding = const EdgeInsets.symmetric(horizontal: 3, vertical: 4), - this.columnBackgroundColor = Colors.transparent, + this.groupBackgroundColor = Colors.transparent, }); } -class AFBoard extends StatelessWidget { +class AppFlowyBoard extends StatelessWidget { /// The direction to use as the main axis. final Axis direction = Axis.vertical; - /// + /// The widget that will be rendered as the background of the board. final Widget? background; + /// The [cardBuilder] function which will be invoked on each card build. + /// The [cardBuilder] takes the [BuildContext],[AppFlowyBoardGroupData] and + /// the corresponding [AppFlowyGroupItem]. /// - final AFBoardColumnCardBuilder cardBuilder; + /// must return a widget. + final AppFlowyBoardCardBuilder cardBuilder; + + /// The [headerBuilder] function which will be invoked on each group build. + /// The [headerBuilder] takes the [BuildContext] and [AppFlowyBoardGroupData]. + /// + /// must return a widget. + final AppFlowyBoardHeaderBuilder? headerBuilder; + + /// The [footerBuilder] function which will be invoked on each group build. + /// The [footerBuilder] takes the [BuildContext] and [AppFlowyBoardGroupData]. + /// + /// must return a widget. + final AppFlowyBoardFooterBuilder? footerBuilder; /// - final AFBoardColumnHeaderBuilder? headerBuilder; + final AppFlowyBoardDataController dataController; - /// - final AFBoardColumnFooterBuilder? footerBuilder; - - /// - final AFBoardDataController dataController; - - final BoxConstraints columnConstraints; + final BoxConstraints groupConstraints; /// late final BoardPhantomController phantomController; final ScrollController? scrollController; - final AFBoardConfig config; + final AppFlowyBoardConfig config; final AFBoardScrollManager? scrollManager; - final BoardColumnsState _columnState = BoardColumnsState(); + final BoardGroupsState _groupState = BoardGroupsState(); - AFBoard({ + AppFlowyBoard({ required this.dataController, required this.cardBuilder, this.background, @@ -82,13 +90,13 @@ class AFBoard extends StatelessWidget { this.headerBuilder, this.scrollController, this.scrollManager, - this.columnConstraints = const BoxConstraints(maxWidth: 200), - this.config = const AFBoardConfig(), + this.groupConstraints = const BoxConstraints(maxWidth: 200), + this.config = const AppFlowyBoardConfig(), Key? key, }) : super(key: key) { phantomController = BoardPhantomController( delegate: dataController, - columnsState: _columnState, + groupsState: _groupState, ); } @@ -96,10 +104,10 @@ class AFBoard extends StatelessWidget { Widget build(BuildContext context) { return ChangeNotifierProvider.value( value: dataController, - child: Consumer( + child: Consumer( builder: (context, notifier, child) { if (scrollManager != null) { - scrollManager!._columnState = _columnState; + scrollManager!._groupState = _groupState; } return AFBoardContent( @@ -107,15 +115,15 @@ class AFBoard extends StatelessWidget { dataController: dataController, scrollController: scrollController, scrollManager: scrollManager, - columnsState: _columnState, + columnsState: _groupState, background: background, delegate: phantomController, - columnConstraints: columnConstraints, + columnConstraints: groupConstraints, cardBuilder: cardBuilder, - footBuilder: footerBuilder, + footerBuilder: footerBuilder, headerBuilder: headerBuilder, phantomController: phantomController, - onReorder: dataController.moveColumn, + onReorder: dataController.moveGroup, ); }, ), @@ -128,22 +136,22 @@ class AFBoardContent extends StatefulWidget { final OnDragStarted? onDragStarted; final OnReorder onReorder; final OnDragEnded? onDragEnded; - final AFBoardDataController dataController; + final AppFlowyBoardDataController dataController; final Widget? background; - final AFBoardConfig config; + final AppFlowyBoardConfig config; final ReorderFlexConfig reorderFlexConfig; final BoxConstraints columnConstraints; final AFBoardScrollManager? scrollManager; - final BoardColumnsState columnsState; + final BoardGroupsState columnsState; /// - final AFBoardColumnCardBuilder cardBuilder; + final AppFlowyBoardCardBuilder cardBuilder; /// - final AFBoardColumnHeaderBuilder? headerBuilder; + final AppFlowyBoardHeaderBuilder? headerBuilder; /// - final AFBoardColumnFooterBuilder? footBuilder; + final AppFlowyBoardFooterBuilder? footerBuilder; final OverlapDragTargetDelegate delegate; @@ -162,7 +170,7 @@ class AFBoardContent extends StatefulWidget { this.background, required this.columnConstraints, required this.cardBuilder, - this.footBuilder, + this.footerBuilder, this.headerBuilder, required this.phantomController, Key? key, @@ -178,13 +186,15 @@ class _AFBoardContentState extends State { GlobalKey(debugLabel: '$AFBoardContent overlay key'); late BoardOverlayEntry _overlayEntry; + final Map _reorderFlexKeys = {}; + @override void initState() { _overlayEntry = BoardOverlayEntry( builder: (BuildContext context) { final interceptor = OverlappingDragTargetInterceptor( reorderFlexId: widget.dataController.identifier, - acceptedReorderFlexId: widget.dataController.columnIds, + acceptedReorderFlexId: widget.dataController.groupIds, delegate: widget.delegate, columnsState: widget.columnsState, ); @@ -233,40 +243,45 @@ class _AFBoardContentState extends State { List _buildColumns() { final List children = - widget.dataController.columnDatas.asMap().entries.map( + widget.dataController.groupDatas.asMap().entries.map( (item) { final columnData = item.value; final columnIndex = item.key; - final dataSource = _BoardColumnDataSourceImpl( - columnId: columnData.id, + final dataSource = _BoardGroupDataSourceImpl( + groupId: columnData.id, dataController: widget.dataController, ); + if (_reorderFlexKeys[columnData.id] == null) { + _reorderFlexKeys[columnData.id] = GlobalObjectKey(columnData.id); + } + + GlobalObjectKey reorderFlexKey = _reorderFlexKeys[columnData.id]!; return ChangeNotifierProvider.value( key: ValueKey(columnData.id), - value: widget.dataController.getColumnController(columnData.id), - child: Consumer( + value: widget.dataController.getGroupController(columnData.id), + child: Consumer( builder: (context, value, child) { - final boardColumn = AFBoardColumnWidget( + final boardColumn = AppFlowyBoardGroupWidget( + reorderFlexKey: reorderFlexKey, // key: PageStorageKey(columnData.id), margin: _marginFromIndex(columnIndex), - itemMargin: widget.config.columnItemPadding, + itemMargin: widget.config.groupItemPadding, headerBuilder: _buildHeader, - footBuilder: widget.footBuilder, + footerBuilder: widget.footerBuilder, cardBuilder: widget.cardBuilder, dataSource: dataSource, scrollController: ScrollController(), phantomController: widget.phantomController, - onReorder: widget.dataController.moveColumnItem, + onReorder: widget.dataController.moveGroupItem, cornerRadius: widget.config.cornerRadius, - backgroundColor: widget.config.columnBackgroundColor, + backgroundColor: widget.config.groupBackgroundColor, dragStateStorage: widget.columnsState, dragTargetIndexKeyStorage: widget.columnsState, ); - widget.columnsState.addColumn(columnData.id, boardColumn); - + widget.columnsState.addGroup(columnData.id, boardColumn); return ConstrainedBox( constraints: widget.columnConstraints, child: boardColumn, @@ -282,79 +297,79 @@ class _AFBoardContentState extends State { Widget? _buildHeader( BuildContext context, - AFBoardColumnData columnData, + AppFlowyBoardGroupData groupData, ) { if (widget.headerBuilder == null) { return null; } - return Selector( - selector: (context, controller) => controller.columnData.headerData, + return Selector( + selector: (context, controller) => controller.groupData.headerData, builder: (context, headerData, _) { - return widget.headerBuilder!(context, columnData)!; + return widget.headerBuilder!(context, groupData)!; }, ); } EdgeInsets _marginFromIndex(int index) { - if (widget.dataController.columnDatas.isEmpty) { - return widget.config.columnPadding; + if (widget.dataController.groupDatas.isEmpty) { + return widget.config.groupPadding; } if (index == 0) { - return EdgeInsets.only(right: widget.config.columnPadding.right); + return EdgeInsets.only(right: widget.config.groupPadding.right); } - if (index == widget.dataController.columnDatas.length - 1) { - return EdgeInsets.only(left: widget.config.columnPadding.left); + if (index == widget.dataController.groupDatas.length - 1) { + return EdgeInsets.only(left: widget.config.groupPadding.left); } - return widget.config.columnPadding; + return widget.config.groupPadding; } } -class _BoardColumnDataSourceImpl extends AFBoardColumnDataDataSource { - String columnId; - final AFBoardDataController dataController; +class _BoardGroupDataSourceImpl extends AppFlowyBoardGroupDataDataSource { + String groupId; + final AppFlowyBoardDataController dataController; - _BoardColumnDataSourceImpl({ - required this.columnId, + _BoardGroupDataSourceImpl({ + required this.groupId, required this.dataController, }); @override - AFBoardColumnData get columnData => - dataController.getColumnController(columnId)!.columnData; + AppFlowyBoardGroupData get groupData => + dataController.getGroupController(groupId)!.groupData; @override - List get acceptedColumnIds => dataController.columnIds; + List get acceptedGroupIds => dataController.groupIds; } -class BoardColumnContext { - GlobalKey? columnKey; +class BoardGroupContext { + GlobalKey? groupKey; DraggingState? draggingState; } -class BoardColumnsState extends DraggingStateStorage +class BoardGroupsState extends DraggingStateStorage with ReorderDragTargetIndexKeyStorage { - /// Quick access to the [AFBoardColumnWidget] - final Map columnKeys = {}; - final Map columnDragStates = {}; - final Map> columnDragDragTargets = {}; + /// Quick access to the [AppFlowyBoardGroupWidget] + final Map groupKeys = {}; + final Map groupDragStates = {}; + final Map> groupDragDragTargets = {}; - void addColumn(String columnId, AFBoardColumnWidget columnWidget) { - columnKeys[columnId] = columnWidget.globalKey; + void addGroup(String groupId, AppFlowyBoardGroupWidget groupWidget) { + groupKeys[groupId] = groupWidget.reorderFlexKey; } - ReorderFlexState? getReorderFlexState({required String columnId}) { - final flexGlobalKey = columnKeys[columnId]; + ReorderFlexState? getReorderFlexState({required String groupId}) { + final flexGlobalKey = groupKeys[groupId]; if (flexGlobalKey == null) return null; if (flexGlobalKey.currentState is! ReorderFlexState) return null; final state = flexGlobalKey.currentState as ReorderFlexState; return state; } - ReorderFlex? getReorderFlex({required String columnId}) { - final flexGlobalKey = columnKeys[columnId]; + ReorderFlex? getReorderFlex({required String groupId}) { + final flexGlobalKey = groupKeys[groupId]; if (flexGlobalKey == null) return null; if (flexGlobalKey.currentWidget is! ReorderFlex) return null; final widget = flexGlobalKey.currentWidget as ReorderFlex; @@ -363,18 +378,18 @@ class BoardColumnsState extends DraggingStateStorage @override DraggingState? read(String reorderFlexId) { - return columnDragStates[reorderFlexId]; + return groupDragStates[reorderFlexId]; } @override void write(String reorderFlexId, DraggingState state) { Log.trace('$reorderFlexId Write dragging state: $state'); - columnDragStates[reorderFlexId] = state; + groupDragStates[reorderFlexId] = state; } @override void remove(String reorderFlexId) { - columnDragStates.remove(reorderFlexId); + groupDragStates.remove(reorderFlexId); } @override @@ -383,20 +398,20 @@ class BoardColumnsState extends DraggingStateStorage String key, GlobalObjectKey> value, ) { - Map? column = columnDragDragTargets[reorderFlexId]; - if (column == null) { - column = {}; - columnDragDragTargets[reorderFlexId] = column; + Map? group = groupDragDragTargets[reorderFlexId]; + if (group == null) { + group = {}; + groupDragDragTargets[reorderFlexId] = group; } - column[key] = value; + group[key] = value; } @override GlobalObjectKey>? readKey( String reorderFlexId, String key) { - Map? column = columnDragDragTargets[reorderFlexId]; - if (column != null) { - return column[key]; + Map? group = groupDragDragTargets[reorderFlexId]; + if (group != null) { + return group[key]; } else { return null; } 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 ce998b365e..9723f97807 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 @@ -9,49 +9,49 @@ import '../reorder_flex/reorder_flex.dart'; import '../reorder_flex/drag_target_interceptor.dart'; import 'board_column_data.dart'; -typedef OnColumnDragStarted = void Function(int index); +typedef OnGroupDragStarted = void Function(int index); -typedef OnColumnDragEnded = void Function(String listId); +typedef OnGroupDragEnded = void Function(String listId); -typedef OnColumnReorder = void Function( +typedef OnGroupReorder = void Function( String listId, int fromIndex, int toIndex, ); -typedef OnColumnDeleted = void Function(String listId, int deletedIndex); +typedef OnGroupDeleted = void Function(String listId, int deletedIndex); -typedef OnColumnInserted = void Function(String listId, int insertedIndex); +typedef OnGroupInserted = void Function(String listId, int insertedIndex); -typedef AFBoardColumnCardBuilder = Widget Function( +typedef AppFlowyBoardCardBuilder = Widget Function( BuildContext context, - AFBoardColumnData columnData, - AFColumnItem item, + AppFlowyBoardGroupData groupData, + AppFlowyGroupItem item, ); -typedef AFBoardColumnHeaderBuilder = Widget? Function( +typedef AppFlowyBoardHeaderBuilder = Widget? Function( BuildContext context, - AFBoardColumnData columnData, + AppFlowyBoardGroupData groupData, ); -typedef AFBoardColumnFooterBuilder = Widget Function( +typedef AppFlowyBoardFooterBuilder = Widget Function( BuildContext context, - AFBoardColumnData columnData, + AppFlowyBoardGroupData groupData, ); -abstract class AFBoardColumnDataDataSource extends ReoderFlexDataSource { - AFBoardColumnData get columnData; +abstract class AppFlowyBoardGroupDataDataSource extends ReoderFlexDataSource { + AppFlowyBoardGroupData get groupData; - List get acceptedColumnIds; + List get acceptedGroupIds; @override - String get identifier => columnData.id; + String get identifier => groupData.id; @override - UnmodifiableListView get items => columnData.items; + UnmodifiableListView get items => groupData.items; void debugPrint() { - String msg = '[$AFBoardColumnDataDataSource] $columnData data: '; + String msg = '[$AppFlowyBoardGroupDataDataSource] $groupData data: '; for (var element in items) { msg = '$msg$element,'; } @@ -60,25 +60,25 @@ abstract class AFBoardColumnDataDataSource extends ReoderFlexDataSource { } } -/// [AFBoardColumnWidget] represents the column of the Board. +/// [AppFlowyBoardGroupWidget] represents the column of the Board. /// -class AFBoardColumnWidget extends StatefulWidget { - final AFBoardColumnDataDataSource dataSource; +class AppFlowyBoardGroupWidget extends StatefulWidget { + final AppFlowyBoardGroupDataDataSource dataSource; final ScrollController? scrollController; final ReorderFlexConfig config; - final OnColumnDragStarted? onDragStarted; - final OnColumnReorder onReorder; - final OnColumnDragEnded? onDragEnded; + final OnGroupDragStarted? onDragStarted; + final OnGroupReorder onReorder; + final OnGroupDragEnded? onDragEnded; final BoardPhantomController phantomController; - String get columnId => dataSource.columnData.id; + String get groupId => dataSource.groupData.id; - final AFBoardColumnCardBuilder cardBuilder; + final AppFlowyBoardCardBuilder cardBuilder; - final AFBoardColumnHeaderBuilder? headerBuilder; + final AppFlowyBoardHeaderBuilder? headerBuilder; - final AFBoardColumnFooterBuilder? footBuilder; + final AppFlowyBoardFooterBuilder? footerBuilder; final EdgeInsets margin; @@ -92,12 +92,13 @@ class AFBoardColumnWidget extends StatefulWidget { final ReorderDragTargetIndexKeyStorage? dragTargetIndexKeyStorage; - final GlobalObjectKey globalKey; + final GlobalObjectKey reorderFlexKey; - AFBoardColumnWidget({ + const AppFlowyBoardGroupWidget({ Key? key, + required this.reorderFlexKey, this.headerBuilder, - this.footBuilder, + this.footerBuilder, required this.cardBuilder, required this.onReorder, required this.dataSource, @@ -111,59 +112,59 @@ class AFBoardColumnWidget extends StatefulWidget { this.itemMargin = EdgeInsets.zero, this.cornerRadius = 0.0, this.backgroundColor = Colors.transparent, - }) : globalKey = GlobalObjectKey(dataSource.columnData.id), - config = const ReorderFlexConfig(setStateWhenEndDrag: false), + }) : config = const ReorderFlexConfig(setStateWhenEndDrag: false), super(key: key); @override - State createState() => _AFBoardColumnWidgetState(); + State createState() => + _AppFlowyBoardGroupWidgetState(); } -class _AFBoardColumnWidgetState extends State { +class _AppFlowyBoardGroupWidgetState extends State { final GlobalKey _columnOverlayKey = - GlobalKey(debugLabel: '$AFBoardColumnWidget overlay key'); + GlobalKey(debugLabel: '$AppFlowyBoardGroupWidget overlay key'); late BoardOverlayEntry _overlayEntry; @override void initState() { _overlayEntry = BoardOverlayEntry( builder: (BuildContext context) { - final children = widget.dataSource.columnData.items + final children = widget.dataSource.groupData.items .map((item) => _buildWidget(context, item)) .toList(); final header = - widget.headerBuilder?.call(context, widget.dataSource.columnData); + widget.headerBuilder?.call(context, widget.dataSource.groupData); final footer = - widget.footBuilder?.call(context, widget.dataSource.columnData); + widget.footerBuilder?.call(context, widget.dataSource.groupData); final interceptor = CrossReorderFlexDragTargetInterceptor( - reorderFlexId: widget.columnId, + reorderFlexId: widget.groupId, delegate: widget.phantomController, - acceptedReorderFlexIds: widget.dataSource.acceptedColumnIds, + acceptedReorderFlexIds: widget.dataSource.acceptedGroupIds, draggableTargetBuilder: PhantomDraggableBuilder(), ); Widget reorderFlex = ReorderFlex( - key: widget.globalKey, + key: widget.reorderFlexKey, dragStateStorage: widget.dragStateStorage, dragTargetIndexKeyStorage: widget.dragTargetIndexKeyStorage, scrollController: widget.scrollController, config: widget.config, onDragStarted: (index) { - widget.phantomController.columnStartDragging(widget.columnId); + widget.phantomController.groupStartDragging(widget.groupId); widget.onDragStarted?.call(index); }, onReorder: ((fromIndex, toIndex) { - if (widget.phantomController.isFromColumn(widget.columnId)) { - widget.onReorder(widget.columnId, fromIndex, toIndex); + if (widget.phantomController.isFromGroup(widget.groupId)) { + widget.onReorder(widget.groupId, fromIndex, toIndex); widget.phantomController.transformIndex(fromIndex, toIndex); } }), onDragEnded: () { - widget.phantomController.columnEndDragging(widget.columnId); - widget.onDragEnded?.call(widget.columnId); + widget.phantomController.groupEndDragging(widget.groupId); + widget.onDragEnded?.call(widget.groupId); widget.dataSource.debugPrint(); }, dataSource: widget.dataSource, @@ -171,6 +172,10 @@ class _AFBoardColumnWidgetState extends State { children: children, ); + reorderFlex = Expanded( + child: Padding(padding: widget.itemMargin, child: reorderFlex), + ); + return Container( margin: widget.margin, clipBehavior: Clip.hardEdge, @@ -181,9 +186,7 @@ class _AFBoardColumnWidgetState extends State { child: Column( children: [ if (header != null) header, - Expanded( - child: Padding(padding: widget.itemMargin, child: reorderFlex), - ), + reorderFlex, if (footer != null) footer, ], ), @@ -202,15 +205,15 @@ class _AFBoardColumnWidgetState extends State { ); } - Widget _buildWidget(BuildContext context, AFColumnItem item) { - if (item is PhantomColumnItem) { + Widget _buildWidget(BuildContext context, AppFlowyGroupItem item) { + if (item is PhantomGroupItem) { return PassthroughPhantomWidget( key: UniqueKey(), opacity: widget.config.draggingWidgetOpacity, passthroughPhantomContext: item.phantomContext, ); } else { - return widget.cardBuilder(context, widget.dataSource.columnData, item); + return widget.cardBuilder(context, widget.dataSource.groupData, item); } } } diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart index bc442acd2a..1a45dce39b 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart @@ -5,14 +5,14 @@ import 'package:flutter/material.dart'; import '../../utils/log.dart'; import '../reorder_flex/reorder_flex.dart'; -abstract class AFColumnItem extends ReoderFlexItem { +abstract class AppFlowyGroupItem extends ReoderFlexItem { bool get isPhantom => false; @override String toString() => id; } -/// [AFBoardColumnDataController] is used to handle the [AFBoardColumnData]. +/// [AFBoardGroupDataController] is used to handle the [AppFlowyBoardGroupData]. /// * Remove an item by calling [removeAt] method. /// * Move item to another position by calling [move] method. /// * Insert item to index by calling [insert] method @@ -20,23 +20,23 @@ abstract class AFColumnItem extends ReoderFlexItem { /// /// All there operations will notify listeners by default. /// -class AFBoardColumnDataController extends ChangeNotifier with EquatableMixin { - final AFBoardColumnData columnData; +class AFBoardGroupDataController extends ChangeNotifier with EquatableMixin { + final AppFlowyBoardGroupData groupData; - AFBoardColumnDataController({ - required this.columnData, + AFBoardGroupDataController({ + required this.groupData, }); @override - List get props => columnData.props; + List get props => groupData.props; - /// Returns the readonly List - UnmodifiableListView get items => - UnmodifiableListView(columnData.items); + /// Returns the readonly List + UnmodifiableListView get items => + UnmodifiableListView(groupData.items); - void updateColumnName(String newName) { - if (columnData.headerData.columnName != newName) { - columnData.headerData.columnName = newName; + void updateGroupName(String newName) { + if (groupData.headerData.groupName != newName) { + groupData.headerData.groupName = newName; notifyListeners(); } } @@ -46,19 +46,18 @@ class AFBoardColumnDataController extends ChangeNotifier with EquatableMixin { /// * [notify] the default value of [notify] is true, it will notify the /// listener. Set to [false] if you do not want to notify the listeners. /// - AFColumnItem removeAt(int index, {bool notify = true}) { + AppFlowyGroupItem removeAt(int index, {bool notify = true}) { assert(index >= 0); - Log.debug( - '[$AFBoardColumnDataController] $columnData remove item at $index'); - final item = columnData._items.removeAt(index); + Log.debug('[$AFBoardGroupDataController] $groupData remove item at $index'); + final item = groupData._items.removeAt(index); if (notify) { notifyListeners(); } return item; } - void removeWhere(bool Function(AFColumnItem) condition) { + void removeWhere(bool Function(AppFlowyGroupItem) condition) { final index = items.indexWhere(condition); if (index != -1) { removeAt(index); @@ -75,9 +74,9 @@ class AFBoardColumnDataController extends ChangeNotifier with EquatableMixin { return false; } Log.debug( - '[$AFBoardColumnDataController] $columnData move item from $fromIndex to $toIndex'); - final item = columnData._items.removeAt(fromIndex); - columnData._items.insert(toIndex, item); + '[$AFBoardGroupDataController] $groupData move item from $fromIndex to $toIndex'); + final item = groupData._items.removeAt(fromIndex); + groupData._items.insert(toIndex, item); notifyListeners(); return true; } @@ -86,18 +85,18 @@ class AFBoardColumnDataController extends ChangeNotifier with EquatableMixin { /// is true. /// /// The default value of [notify] is true. - bool insert(int index, AFColumnItem item, {bool notify = true}) { + bool insert(int index, AppFlowyGroupItem item, {bool notify = true}) { assert(index >= 0); Log.debug( - '[$AFBoardColumnDataController] $columnData insert $item at $index'); + '[$AFBoardGroupDataController] $groupData insert $item at $index'); if (_containsItem(item)) { return false; } else { - if (columnData._items.length > index) { - columnData._items.insert(index, item); + if (groupData._items.length > index) { + groupData._items.insert(index, item); } else { - columnData._items.add(item); + groupData._items.add(item); } if (notify) notifyListeners(); @@ -105,74 +104,75 @@ class AFBoardColumnDataController extends ChangeNotifier with EquatableMixin { } } - bool add(AFColumnItem item, {bool notify = true}) { + bool add(AppFlowyGroupItem item, {bool notify = true}) { if (_containsItem(item)) { return false; } else { - columnData._items.add(item); + groupData._items.add(item); if (notify) notifyListeners(); return true; } } /// Replace the item at index with the [newItem]. - void replace(int index, AFColumnItem newItem) { - if (columnData._items.isEmpty) { - columnData._items.add(newItem); - Log.debug('[$AFBoardColumnDataController] $columnData add $newItem'); + void replace(int index, AppFlowyGroupItem newItem) { + if (groupData._items.isEmpty) { + groupData._items.add(newItem); + Log.debug('[$AFBoardGroupDataController] $groupData add $newItem'); } else { - if (index >= columnData._items.length) { + if (index >= groupData._items.length) { return; } - final removedItem = columnData._items.removeAt(index); - columnData._items.insert(index, newItem); + final removedItem = groupData._items.removeAt(index); + groupData._items.insert(index, newItem); Log.debug( - '[$AFBoardColumnDataController] $columnData replace $removedItem with $newItem at $index'); + '[$AFBoardGroupDataController] $groupData replace $removedItem with $newItem at $index'); } notifyListeners(); } - void replaceOrInsertItem(AFColumnItem newItem) { - final index = columnData._items.indexWhere((item) => item.id == newItem.id); + void replaceOrInsertItem(AppFlowyGroupItem newItem) { + final index = groupData._items.indexWhere((item) => item.id == newItem.id); if (index != -1) { - columnData._items.removeAt(index); - columnData._items.insert(index, newItem); + groupData._items.removeAt(index); + groupData._items.insert(index, newItem); notifyListeners(); } else { - columnData._items.add(newItem); + groupData._items.add(newItem); notifyListeners(); } } - bool _containsItem(AFColumnItem item) { - return columnData._items.indexWhere((element) => element.id == item.id) != + bool _containsItem(AppFlowyGroupItem item) { + return groupData._items.indexWhere((element) => element.id == item.id) != -1; } } -/// [AFBoardColumnData] represents the data of each Column of the Board. -class AFBoardColumnData extends ReoderFlexItem with EquatableMixin { +/// [AppFlowyBoardGroupData] represents the data of each group of the Board. +class AppFlowyBoardGroupData extends ReoderFlexItem + with EquatableMixin { @override final String id; - AFBoardColumnHeaderData headerData; - final List _items; + AppFlowyBoardGroupHeaderData headerData; + final List _items; final CustomData? customData; - AFBoardColumnData({ + AppFlowyBoardGroupData({ this.customData, required this.id, required String name, - List items = const [], + List items = const [], }) : _items = items, - headerData = AFBoardColumnHeaderData( - columnId: id, - columnName: name, + headerData = AppFlowyBoardGroupHeaderData( + groupId: id, + groupName: name, ); - /// Returns the readonly List - UnmodifiableListView get items => + /// Returns the readonly List + UnmodifiableListView get items => UnmodifiableListView([..._items]); @override @@ -180,13 +180,14 @@ class AFBoardColumnData extends ReoderFlexItem with EquatableMixin { @override String toString() { - return 'Column:[$id]'; + return 'Group:[$id]'; } } -class AFBoardColumnHeaderData { - String columnId; - String columnName; +class AppFlowyBoardGroupHeaderData { + String groupId; + String groupName; - AFBoardColumnHeaderData({required this.columnId, required this.columnName}); + AppFlowyBoardGroupHeaderData( + {required this.groupId, required this.groupName}); } 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 47e74b37f5..7cd5642791 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 @@ -8,213 +8,213 @@ import 'reorder_flex/reorder_flex.dart'; import 'package:flutter/material.dart'; import 'reorder_phantom/phantom_controller.dart'; -typedef OnMoveColumn = void Function( - String fromColumnId, +typedef OnMoveGroup = void Function( + String fromGroupId, int fromIndex, - String toColumnId, + String toGroupId, int toIndex, ); -typedef OnMoveColumnItem = void Function( - String columnId, +typedef OnMoveGroupItem = void Function( + String groupId, int fromIndex, int toIndex, ); -typedef OnMoveColumnItemToColumn = void Function( - String fromColumnId, +typedef OnMoveGroupItemToGroup = void Function( + String fromGroupId, int fromIndex, - String toColumnId, + String toGroupId, int toIndex, ); -class AFBoardDataController extends ChangeNotifier +class AppFlowyBoardDataController extends ChangeNotifier with EquatableMixin, BoardPhantomControllerDelegate, ReoderFlexDataSource { - final List _columnDatas = []; - final OnMoveColumn? onMoveColumn; - final OnMoveColumnItem? onMoveColumnItem; - final OnMoveColumnItemToColumn? onMoveColumnItemToColumn; + final List _groupDatas = []; + final OnMoveGroup? onMoveGroup; + final OnMoveGroupItem? onMoveGroupItem; + final OnMoveGroupItemToGroup? onMoveGroupItemToGroup; - List get columnDatas => _columnDatas; + UnmodifiableListView get groupDatas => + UnmodifiableListView(_groupDatas); - List get columnIds => - _columnDatas.map((columnData) => columnData.id).toList(); + List get groupIds => + _groupDatas.map((groupData) => groupData.id).toList(); - final LinkedHashMap _columnControllers = + final LinkedHashMap _groupControllers = LinkedHashMap(); - AFBoardDataController({ - this.onMoveColumn, - this.onMoveColumnItem, - this.onMoveColumnItemToColumn, + AppFlowyBoardDataController({ + this.onMoveGroup, + this.onMoveGroupItem, + this.onMoveGroupItemToGroup, }); - void addColumn(AFBoardColumnData columnData, {bool notify = true}) { - if (_columnControllers[columnData.id] != null) return; + void addGroup(AppFlowyBoardGroupData groupData, {bool notify = true}) { + if (_groupControllers[groupData.id] != null) return; - final controller = AFBoardColumnDataController(columnData: columnData); - _columnDatas.add(columnData); - _columnControllers[columnData.id] = controller; + final controller = AFBoardGroupDataController(groupData: groupData); + _groupDatas.add(groupData); + _groupControllers[groupData.id] = controller; if (notify) notifyListeners(); } - void addColumns(List columns, {bool notify = true}) { - for (final column in columns) { - addColumn(column, notify: false); + void addGroups(List groups, {bool notify = true}) { + for (final column in groups) { + addGroup(column, notify: false); } - if (columns.isNotEmpty && notify) notifyListeners(); + if (groups.isNotEmpty && notify) notifyListeners(); } - void removeColumn(String columnId, {bool notify = true}) { - final index = _columnDatas.indexWhere((column) => column.id == columnId); + void removeGroup(String groupId, {bool notify = true}) { + final index = _groupDatas.indexWhere((group) => group.id == groupId); if (index == -1) { Log.warn( - 'Try to remove Column:[$columnId] failed. Column:[$columnId] not exist'); + 'Try to remove Group:[$groupId] failed. Group:[$groupId] not exist'); } if (index != -1) { - _columnDatas.removeAt(index); - _columnControllers.remove(columnId); + _groupDatas.removeAt(index); + _groupControllers.remove(groupId); if (notify) notifyListeners(); } } - void removeColumns(List columnIds, {bool notify = true}) { - for (final columnId in columnIds) { - removeColumn(columnId, notify: false); + void removeGroups(List groupIds, {bool notify = true}) { + for (final groupId in groupIds) { + removeGroup(groupId, notify: false); } - if (columnIds.isNotEmpty && notify) notifyListeners(); + if (groupIds.isNotEmpty && notify) notifyListeners(); } void clear() { - _columnDatas.clear(); - _columnControllers.clear(); + _groupDatas.clear(); + _groupControllers.clear(); notifyListeners(); } - AFBoardColumnDataController? getColumnController(String columnId) { - final columnController = _columnControllers[columnId]; - if (columnController == null) { - Log.warn('Column:[$columnId] \'s controller is not exist'); + AFBoardGroupDataController? getGroupController(String groupId) { + final groupController = _groupControllers[groupId]; + if (groupController == null) { + Log.warn('Group:[$groupId] \'s controller is not exist'); } - return columnController; + return groupController; } - void moveColumn(int fromIndex, int toIndex, {bool notify = true}) { - final toColumnData = _columnDatas[toIndex]; - final fromColumnData = _columnDatas.removeAt(fromIndex); + void moveGroup(int fromIndex, int toIndex, {bool notify = true}) { + final toGroupData = _groupDatas[toIndex]; + final fromGroupData = _groupDatas.removeAt(fromIndex); - _columnDatas.insert(toIndex, fromColumnData); - onMoveColumn?.call(fromColumnData.id, fromIndex, toColumnData.id, toIndex); + _groupDatas.insert(toIndex, fromGroupData); + onMoveGroup?.call(fromGroupData.id, fromIndex, toGroupData.id, toIndex); if (notify) notifyListeners(); } - void moveColumnItem(String columnId, int fromIndex, int toIndex) { - if (getColumnController(columnId)?.move(fromIndex, toIndex) ?? false) { - onMoveColumnItem?.call(columnId, fromIndex, toIndex); + void moveGroupItem(String groupId, int fromIndex, int toIndex) { + if (getGroupController(groupId)?.move(fromIndex, toIndex) ?? false) { + onMoveGroupItem?.call(groupId, fromIndex, toIndex); } } - void addColumnItem(String columnId, AFColumnItem item) { - getColumnController(columnId)?.add(item); + void addGroupItem(String groupId, AppFlowyGroupItem item) { + getGroupController(groupId)?.add(item); } - void insertColumnItem(String columnId, int index, AFColumnItem item) { - getColumnController(columnId)?.insert(index, item); + void insertGroupItem(String groupId, int index, AppFlowyGroupItem item) { + getGroupController(groupId)?.insert(index, item); } - void removeColumnItem(String columnId, String itemId) { - getColumnController(columnId)?.removeWhere((item) => item.id == itemId); + void removeGroupItem(String groupId, String itemId) { + getGroupController(groupId)?.removeWhere((item) => item.id == itemId); } - void updateColumnItem(String columnId, AFColumnItem item) { - getColumnController(columnId)?.replaceOrInsertItem(item); + void updateGroupItem(String groupId, AppFlowyGroupItem item) { + getGroupController(groupId)?.replaceOrInsertItem(item); } @override @protected - void swapColumnItem( - String fromColumnId, - int fromColumnIndex, - String toColumnId, - int toColumnIndex, + void swapGroupItem( + String fromGroupId, + int fromGroupIndex, + String toGroupId, + int toGroupIndex, ) { - final fromColumnController = getColumnController(fromColumnId)!; - final toColumnController = getColumnController(toColumnId)!; - final item = fromColumnController.removeAt(fromColumnIndex); - if (toColumnController.items.length > toColumnIndex) { - assert(toColumnController.items[toColumnIndex] is PhantomColumnItem); + final fromGroupController = getGroupController(fromGroupId)!; + final toGroupController = getGroupController(toGroupId)!; + final item = fromGroupController.removeAt(fromGroupIndex); + if (toGroupController.items.length > toGroupIndex) { + assert(toGroupController.items[toGroupIndex] is PhantomGroupItem); } - toColumnController.replace(toColumnIndex, item); - onMoveColumnItemToColumn?.call( - fromColumnId, - fromColumnIndex, - toColumnId, - toColumnIndex, + toGroupController.replace(toGroupIndex, item); + onMoveGroupItemToGroup?.call( + fromGroupId, + fromGroupIndex, + toGroupId, + toGroupIndex, ); } @override List get props { - return [_columnDatas]; + return [_groupDatas]; } @override - AFBoardColumnDataController? controller(String columnId) { - return _columnControllers[columnId]; + AFBoardGroupDataController? controller(String groupId) { + return _groupControllers[groupId]; } @override - String get identifier => '$AFBoardDataController'; + String get identifier => '$AppFlowyBoardDataController'; @override UnmodifiableListView get items => - UnmodifiableListView(_columnDatas); + UnmodifiableListView(_groupDatas); @override @protected - bool removePhantom(String columnId) { - final columnController = getColumnController(columnId); - if (columnController == null) { - Log.warn('Can not find the column controller with columnId: $columnId'); + bool removePhantom(String groupId) { + final groupController = getGroupController(groupId); + if (groupController == null) { + Log.warn('Can not find the group controller with groupId: $groupId'); return false; } - final index = columnController.items.indexWhere((item) => item.isPhantom); + final index = groupController.items.indexWhere((item) => item.isPhantom); final isExist = index != -1; if (isExist) { - columnController.removeAt(index); + groupController.removeAt(index); Log.debug( - '[$AFBoardDataController] Column:[$columnId] remove phantom, current count: ${columnController.items.length}'); + '[$AppFlowyBoardDataController] Group:[$groupId] remove phantom, current count: ${groupController.items.length}'); } return isExist; } @override @protected - void updatePhantom(String columnId, int newIndex) { - final columnDataController = getColumnController(columnId)!; - final index = - columnDataController.items.indexWhere((item) => item.isPhantom); + void updatePhantom(String groupId, int newIndex) { + final groupController = getGroupController(groupId)!; + final index = groupController.items.indexWhere((item) => item.isPhantom); if (index != -1) { if (index != newIndex) { Log.trace( - '[$BoardPhantomController] update $columnId:$index to $columnId:$newIndex'); - final item = columnDataController.removeAt(index, notify: false); - columnDataController.insert(newIndex, item, notify: false); + '[$BoardPhantomController] update $groupId:$index to $groupId:$newIndex'); + final item = groupController.removeAt(index, notify: false); + groupController.insert(newIndex, item, notify: false); } } } @override @protected - void insertPhantom(String columnId, int index, PhantomColumnItem item) { - getColumnController(columnId)!.insert(index, item); + void insertPhantom(String groupId, int index, PhantomGroupItem item) { + getGroupController(groupId)!.insert(index, item); } } 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 20f66c0921..97aba2c294 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 @@ -55,7 +55,7 @@ class OverlappingDragTargetInterceptor extends DragTargetInterceptor { final String reorderFlexId; final List acceptedReorderFlexId; final OverlapDragTargetDelegate delegate; - final BoardColumnsState columnsState; + final BoardGroupsState columnsState; Timer? _delayOperation; OverlappingDragTargetInterceptor({ @@ -81,7 +81,7 @@ class OverlappingDragTargetInterceptor extends DragTargetInterceptor { delegate.cancel(); } else { // Ignore the event if the dragTarget overlaps with the other column's dragTargets. - final columnKeys = columnsState.columnDragDragTargets[dragTargetId]; + final columnKeys = columnsState.groupDragDragTargets[dragTargetId]; if (columnKeys != null) { final keys = columnKeys.values.toList(); if (dragTargetData.isOverlapWithWidgets(keys)) { @@ -102,7 +102,7 @@ class OverlappingDragTargetInterceptor extends DragTargetInterceptor { delegate.moveTo(dragTargetId, dragTargetData, index); columnsState - .getReorderFlexState(columnId: dragTargetId) + .getReorderFlexState(groupId: dragTargetId) ?.resetDragTargetIndex(index); } }); @@ -165,13 +165,13 @@ class CrossReorderFlexDragTargetInterceptor extends DragTargetInterceptor { @override void onAccept(FlexDragTargetData dragTargetData) { Log.trace( - '[$CrossReorderFlexDragTargetInterceptor] Column:[$reorderFlexId] on onAccept'); + '[$CrossReorderFlexDragTargetInterceptor] Group:[$reorderFlexId] on onAccept'); } @override void onLeave(FlexDragTargetData dragTargetData) { Log.trace( - '[$CrossReorderFlexDragTargetInterceptor] Column:[$reorderFlexId] on leave'); + '[$CrossReorderFlexDragTargetInterceptor] Group:[$reorderFlexId] on leave'); } @override 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 bff76cfe52..dda8aa7011 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 @@ -49,8 +49,8 @@ class ReorderFlexConfig { /// Determines if setSatte method needs to be called when the drag is complete. /// Default value is [true]. /// - /// If the [ReorderFlex] will be rebuild after the [ReorderFlex]'s children - /// were changed, then the [setStateWhenEndDrag] should set to [false]. + /// If the [ReorderFlex] needs to be rebuild after the [ReorderFlex] end dragging, + /// the [setStateWhenEndDrag] should set to [true]. final bool setStateWhenEndDrag; final bool useMoveAnimation; @@ -252,7 +252,7 @@ class ReorderFlexState extends State } Log.trace( - 'Rebuild: Column:[${dragState.reorderFlexId}] ${dragState.toString()}, childIndex: $childIndex shiftedIndex: $shiftedIndex'); + 'Rebuild: Group:[${dragState.reorderFlexId}] ${dragState.toString()}, childIndex: $childIndex shiftedIndex: $shiftedIndex'); final currentIndex = dragState.currentIndex; final dragPhantomIndex = dragState.phantomIndex; @@ -368,7 +368,7 @@ class ReorderFlexState extends State ), onDragStarted: (draggingWidget, draggingIndex, size) { Log.debug( - "[DragTarget] Column:[${widget.dataSource.identifier}] start dragging item at $draggingIndex"); + "[DragTarget] Group:[${widget.dataSource.identifier}] start dragging item at $draggingIndex"); _startDragging(draggingWidget, draggingIndex, size); widget.onDragStarted?.call(draggingIndex); widget.dragStateStorage?.remove(widget.reorderFlexId); @@ -379,7 +379,7 @@ class ReorderFlexState extends State onDragEnded: (dragTargetData) { if (!mounted) return; Log.debug( - "[DragTarget]: Column:[${widget.dataSource.identifier}] end dragging"); + "[DragTarget]: Group:[${widget.dataSource.identifier}] end dragging"); _notifier.updateDragTargetIndex(-1); onDragEnded() { 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 0f63266e51..f7b06a73fd 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 @@ -8,30 +8,30 @@ import '../reorder_flex/drag_target_interceptor.dart'; import 'phantom_state.dart'; abstract class BoardPhantomControllerDelegate { - AFBoardColumnDataController? controller(String columnId); + AFBoardGroupDataController? controller(String groupId); - bool removePhantom(String columnId); + bool removePhantom(String groupId); - /// Insert the phantom into column + /// Insert the phantom into the group /// - /// * [toColumnId] id of the column + /// * [groupId] id of the group /// * [phantomIndex] the phantom occupies index void insertPhantom( - String columnId, + String groupId, int index, - PhantomColumnItem item, + PhantomGroupItem item, ); - /// Update the column's phantom index if it exists. - /// [toColumnId] the id of the column + /// Update the group's phantom index if it exists. + /// [toGroupId] the id of the group /// [dragTargetIndex] the index of the dragTarget - void updatePhantom(String columnId, int newIndex); + void updatePhantom(String groupId, int newIndex); - void swapColumnItem( - String fromColumnId, - int fromColumnIndex, - String toColumnId, - int toColumnIndex, + void swapGroupItem( + String fromGroupId, + int fromGroupIndex, + String toGroupId, + int toGroupIndex, ); } @@ -39,16 +39,16 @@ class BoardPhantomController extends OverlapDragTargetDelegate with CrossReorderFlexDragTargetDelegate { PhantomRecord? phantomRecord; final BoardPhantomControllerDelegate delegate; - final BoardColumnsState columnsState; - final phantomState = ColumnPhantomState(); + final BoardGroupsState groupsState; + final phantomState = GroupPhantomState(); BoardPhantomController({ required this.delegate, - required this.columnsState, + required this.groupsState, }); - bool isFromColumn(String columnId) { + bool isFromGroup(String groupId) { if (phantomRecord != null) { - return phantomRecord!.fromColumnId == columnId; + return phantomRecord!.fromGroupId == groupId; } else { return true; } @@ -58,32 +58,32 @@ class BoardPhantomController extends OverlapDragTargetDelegate if (phantomRecord == null) { return; } - assert(phantomRecord!.fromColumnIndex == fromIndex); - phantomRecord?.updateFromColumnIndex(toIndex); + assert(phantomRecord!.fromGroupIndex == fromIndex); + phantomRecord?.updateFromGroupIndex(toIndex); } - void columnStartDragging(String columnId) { - phantomState.setColumnIsDragging(columnId, true); + void groupStartDragging(String groupId) { + phantomState.setGroupIsDragging(groupId, true); } - /// Remove the phantom in the column when the column is end dragging. - void columnEndDragging(String columnId) { - phantomState.setColumnIsDragging(columnId, false); + /// Remove the phantom in the group when the group is end dragging. + void groupEndDragging(String groupId) { + phantomState.setGroupIsDragging(groupId, false); if (phantomRecord == null) return; - final fromColumnId = phantomRecord!.fromColumnId; - final toColumnId = phantomRecord!.toColumnId; - if (fromColumnId == columnId) { - phantomState.notifyDidRemovePhantom(toColumnId); + final fromGroupId = phantomRecord!.fromGroupId; + final toGroupId = phantomRecord!.toGroupId; + if (fromGroupId == groupId) { + phantomState.notifyDidRemovePhantom(toGroupId); } - if (phantomRecord!.toColumnId == columnId) { - delegate.swapColumnItem( - fromColumnId, - phantomRecord!.fromColumnIndex, - toColumnId, - phantomRecord!.toColumnIndex, + if (phantomRecord!.toGroupId == groupId) { + delegate.swapGroupItem( + fromGroupId, + phantomRecord!.fromGroupIndex, + toGroupId, + phantomRecord!.toGroupIndex, ); // Log.debug( @@ -92,16 +92,16 @@ class BoardPhantomController extends OverlapDragTargetDelegate } } - /// Remove the phantom in the column if it contains phantom - void _removePhantom(String columnId) { - if (delegate.removePhantom(columnId)) { - phantomState.notifyDidRemovePhantom(columnId); - phantomState.removeColumnListener(columnId); + /// Remove the phantom in the group if it contains phantom + void _removePhantom(String groupId) { + if (delegate.removePhantom(groupId)) { + phantomState.notifyDidRemovePhantom(groupId); + phantomState.removeGroupListener(groupId); } } void _insertPhantom( - String toColumnId, + String toGroupId, FlexDragTargetData dragTargetData, int phantomIndex, ) { @@ -109,38 +109,38 @@ class BoardPhantomController extends OverlapDragTargetDelegate index: phantomIndex, dragTargetData: dragTargetData, ); - phantomState.addColumnListener(toColumnId, phantomContext); + phantomState.addGroupListener(toGroupId, phantomContext); delegate.insertPhantom( - toColumnId, + toGroupId, phantomIndex, - PhantomColumnItem(phantomContext), + PhantomGroupItem(phantomContext), ); - phantomState.notifyDidInsertPhantom(toColumnId, phantomIndex); + phantomState.notifyDidInsertPhantom(toGroupId, phantomIndex); } /// Reset or initial the [PhantomRecord] /// /// - /// * [columnId] the id of the column + /// * [groupId] the id of the group /// * [dragTargetData] /// * [dragTargetIndex] /// void _resetPhantomRecord( - String columnId, + String groupId, FlexDragTargetData dragTargetData, int dragTargetIndex, ) { // Log.debug( - // '[$BoardPhantomController] move Column:[${dragTargetData.reorderFlexId}]:${dragTargetData.draggingIndex} ' - // 'to Column:[$columnId]:$dragTargetIndex'); + // '[$BoardPhantomController] move Group:[${dragTargetData.reorderFlexId}]:${dragTargetData.draggingIndex} ' + // 'to Group:[$groupId]:$dragTargetIndex'); phantomRecord = PhantomRecord( - toColumnId: columnId, - toColumnIndex: dragTargetIndex, - fromColumnId: dragTargetData.reorderFlexId, - fromColumnIndex: dragTargetData.draggingIndex, + toGroupId: groupId, + toGroupIndex: dragTargetIndex, + fromGroupId: dragTargetData.reorderFlexId, + fromGroupIndex: dragTargetData.draggingIndex, ); Log.debug('[$BoardPhantomController] will move: $phantomRecord'); } @@ -158,10 +158,10 @@ class BoardPhantomController extends OverlapDragTargetDelegate return true; } - final isNewDragTarget = phantomRecord!.toColumnId != reorderFlexId; + final isNewDragTarget = phantomRecord!.toGroupId != reorderFlexId; if (isNewDragTarget) { - /// Remove the phantom when the dragTarget is moved from one column to another column. - _removePhantom(phantomRecord!.toColumnId); + /// Remove the phantom when the dragTarget is moved from one group to another group. + _removePhantom(phantomRecord!.toGroupId); _resetPhantomRecord(reorderFlexId, dragTargetData, dragTargetIndex); _insertPhantom(reorderFlexId, dragTargetData, dragTargetIndex); } @@ -177,9 +177,9 @@ class BoardPhantomController extends OverlapDragTargetDelegate phantomRecord?.updateInsertedIndex(dragTargetIndex); assert(phantomRecord != null); - if (phantomRecord!.toColumnId == reorderFlexId) { + if (phantomRecord!.toGroupId == reorderFlexId) { /// Update the existing phantom index - delegate.updatePhantom(phantomRecord!.toColumnId, dragTargetIndex); + delegate.updatePhantom(phantomRecord!.toGroupId, dragTargetIndex); } } @@ -189,8 +189,8 @@ class BoardPhantomController extends OverlapDragTargetDelegate return; } - /// Remove the phantom when the dragTarge is go back to the original column. - _removePhantom(phantomRecord!.toColumnId); + /// Remove the phantom when the dragTarge is go back to the original group. + _removePhantom(phantomRecord!.toGroupId); phantomRecord = null; } @@ -215,63 +215,63 @@ class BoardPhantomController extends OverlapDragTargetDelegate final controller = delegate.controller(dragTargetId); if (controller != null) { - return controller.columnData.items.length; + return controller.groupData.items.length; } else { return 0; } } } -/// Use [PhantomRecord] to record where to remove the column item and where to -/// insert the column item. +/// Use [PhantomRecord] to record where to remove the group item and where to +/// insert the group item. /// -/// [fromColumnId] the column that phantom comes from -/// [fromColumnIndex] the index of the phantom from the original column -/// [toColumnId] the column that the phantom moves into -/// [toColumnIndex] the index of the phantom moves into the column +/// [fromGroupId] the group that phantom comes from +/// [fromGroupIndex] the index of the phantom from the original group +/// [toGroupId] the group that the phantom moves into +/// [toGroupIndex] the index of the phantom moves into the group /// class PhantomRecord { - final String fromColumnId; - int fromColumnIndex; + final String fromGroupId; + int fromGroupIndex; - final String toColumnId; - int toColumnIndex; + final String toGroupId; + int toGroupIndex; PhantomRecord({ - required this.toColumnId, - required this.toColumnIndex, - required this.fromColumnId, - required this.fromColumnIndex, + required this.toGroupId, + required this.toGroupIndex, + required this.fromGroupId, + required this.fromGroupIndex, }); - void updateFromColumnIndex(int index) { - if (fromColumnIndex == index) { + void updateFromGroupIndex(int index) { + if (fromGroupIndex == index) { return; } - fromColumnIndex = index; + fromGroupIndex = index; } void updateInsertedIndex(int index) { - if (toColumnIndex == index) { + if (toGroupIndex == index) { return; } Log.debug( - '[$PhantomRecord] Column:[$toColumnId] update position $toColumnIndex -> $index'); - toColumnIndex = index; + '[$PhantomRecord] Group:[$toGroupId] update position $toGroupIndex -> $index'); + toGroupIndex = index; } @override String toString() { - return 'Column:[$fromColumnId]:$fromColumnIndex to Column:[$toColumnId]:$toColumnIndex'; + return 'Group:[$fromGroupId]:$fromGroupIndex to Group:[$toGroupId]:$toGroupIndex'; } } -class PhantomColumnItem extends AFColumnItem { +class PhantomGroupItem extends AppFlowyGroupItem { final PassthroughPhantomContext phantomContext; - PhantomColumnItem(PassthroughPhantomContext insertedPhantom) + PhantomGroupItem(PassthroughPhantomContext insertedPhantom) : phantomContext = insertedPhantom; @override @@ -305,7 +305,8 @@ class PassthroughPhantomContext extends FakeDragTargetEventTrigger Widget? get draggingWidget => dragTargetData.draggingWidget; - AFColumnItem get itemData => dragTargetData.reorderFlexItem as AFColumnItem; + AppFlowyGroupItem get itemData => + dragTargetData.reorderFlexItem as AppFlowyGroupItem; @override void Function(int?)? onInserted; 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 c550ee3bca..0aeeb86a7a 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 @@ -1,48 +1,48 @@ import 'phantom_controller.dart'; import 'package:flutter/material.dart'; -class ColumnPhantomState { - final _states = {}; +class GroupPhantomState { + final _states = {}; - void setColumnIsDragging(String columnId, bool isDragging) { - _stateWithId(columnId).isDragging = isDragging; + void setGroupIsDragging(String groupId, bool isDragging) { + _stateWithId(groupId).isDragging = isDragging; } - bool isDragging(String columnId) { - return _stateWithId(columnId).isDragging; + bool isDragging(String groupId) { + return _stateWithId(groupId).isDragging; } - void addColumnListener(String columnId, PassthroughPhantomListener listener) { - _stateWithId(columnId).notifier.addListener( + void addGroupListener(String groupId, PassthroughPhantomListener listener) { + _stateWithId(groupId).notifier.addListener( onInserted: (index) => listener.onInserted?.call(index), onDeleted: () => listener.onDragEnded?.call(), ); } - void removeColumnListener(String columnId) { - _stateWithId(columnId).notifier.dispose(); - _states.remove(columnId); + void removeGroupListener(String groupId) { + _stateWithId(groupId).notifier.dispose(); + _states.remove(groupId); } - void notifyDidInsertPhantom(String columnId, int index) { - _stateWithId(columnId).notifier.insert(index); + void notifyDidInsertPhantom(String groupId, int index) { + _stateWithId(groupId).notifier.insert(index); } - void notifyDidRemovePhantom(String columnId) { - _stateWithId(columnId).notifier.remove(); + void notifyDidRemovePhantom(String groupId) { + _stateWithId(groupId).notifier.remove(); } - ColumnState _stateWithId(String columnId) { - var state = _states[columnId]; + GroupState _stateWithId(String groupId) { + var state = _states[groupId]; if (state == null) { - state = ColumnState(); - _states[columnId] = state; + state = GroupState(); + _states[groupId] = state; } return state; } } -class ColumnState { +class GroupState { bool isDragging = false; final notifier = PassthroughPhantomNotifier(); } diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/card.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/card.dart index 77cfc1cb13..61822efbde 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/card.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/card.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; -class AppFlowyColumnItemCard extends StatefulWidget { +class AppFlowyGroupItemCard extends StatefulWidget { final Widget? child; final EdgeInsets margin; final BoxConstraints boxConstraints; final BoxDecoration decoration; - const AppFlowyColumnItemCard({ + const AppFlowyGroupItemCard({ this.child, this.margin = const EdgeInsets.all(4), this.decoration = const BoxDecoration( @@ -18,10 +18,10 @@ class AppFlowyColumnItemCard extends StatefulWidget { }) : super(key: key); @override - State createState() => _AppFlowyColumnItemCardState(); + State createState() => _AppFlowyGroupItemCardState(); } -class _AppFlowyColumnItemCardState extends State { +class _AppFlowyGroupItemCardState extends State { @override Widget build(BuildContext context) { return Padding( diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/footer.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/footer.dart index c877e4fe4d..54ad4e242d 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/footer.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/footer.dart @@ -2,14 +2,14 @@ import 'package:flutter/material.dart'; typedef OnFooterAddButtonClick = void Function(); -class AppFlowyColumnFooter extends StatefulWidget { +class AppFlowyGroupFooter extends StatefulWidget { final double height; final Widget? icon; final Widget? title; final EdgeInsets margin; final OnFooterAddButtonClick? onAddButtonClick; - const AppFlowyColumnFooter({ + const AppFlowyGroupFooter({ this.icon, this.title, this.margin = const EdgeInsets.symmetric(horizontal: 12), @@ -19,10 +19,10 @@ class AppFlowyColumnFooter extends StatefulWidget { }) : super(key: key); @override - State createState() => _AppFlowyColumnFooterState(); + State createState() => _AppFlowyGroupFooterState(); } -class _AppFlowyColumnFooterState extends State { +class _AppFlowyGroupFooterState extends State { @override Widget build(BuildContext context) { return GestureDetector( diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/header.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/header.dart index 88f52c9134..9e17a340ee 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/header.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/header.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; typedef OnHeaderAddButtonClick = void Function(); typedef OnHeaderMoreButtonClick = void Function(); -class AppFlowyColumnHeader extends StatefulWidget { +class AppFlowyGroupHeader extends StatefulWidget { final double height; final Widget? icon; final Widget? title; @@ -13,7 +13,7 @@ class AppFlowyColumnHeader extends StatefulWidget { final OnHeaderAddButtonClick? onAddButtonClick; final OnHeaderMoreButtonClick? onMoreButtonClick; - const AppFlowyColumnHeader({ + const AppFlowyGroupHeader({ required this.height, this.icon, this.title, @@ -26,10 +26,10 @@ class AppFlowyColumnHeader extends StatefulWidget { }) : super(key: key); @override - State createState() => _AppFlowyColumnHeaderState(); + State createState() => _AppFlowyGroupHeaderState(); } -class _AppFlowyColumnHeaderState extends State { +class _AppFlowyGroupHeaderState extends State { @override Widget build(BuildContext context) { List children = []; From 8f5569a0121237458da0b878062121b94b1f86dc Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 6 Sep 2022 10:52:32 +0800 Subject: [PATCH 2/4] chore: update doc --- .../appflowy_board/lib/src/widgets/board.dart | 26 +++---- .../widgets/board_column/board_column.dart | 13 ++-- .../lib/src/widgets/board_data.dart | 68 ++++++++++++++++++- .../reorder_phantom/phantom_controller.dart | 4 +- 4 files changed, 82 insertions(+), 29 deletions(-) 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 7ed69db822..7e98653848 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 @@ -110,7 +110,7 @@ class AppFlowyBoard extends StatelessWidget { scrollManager!._groupState = _groupState; } - return AFBoardContent( + return _AppFlolwyBoardContent( config: config, dataController: dataController, scrollController: scrollController, @@ -131,7 +131,7 @@ class AppFlowyBoard extends StatelessWidget { } } -class AFBoardContent extends StatefulWidget { +class _AppFlolwyBoardContent extends StatefulWidget { final ScrollController? scrollController; final OnDragStarted? onDragStarted; final OnReorder onReorder; @@ -143,21 +143,13 @@ class AFBoardContent extends StatefulWidget { final BoxConstraints columnConstraints; final AFBoardScrollManager? scrollManager; final BoardGroupsState columnsState; - - /// final AppFlowyBoardCardBuilder cardBuilder; - - /// final AppFlowyBoardHeaderBuilder? headerBuilder; - - /// final AppFlowyBoardFooterBuilder? footerBuilder; - final OverlapDragTargetDelegate delegate; - final BoardPhantomController phantomController; - const AFBoardContent({ + const _AppFlolwyBoardContent({ required this.config, required this.onReorder, required this.delegate, @@ -178,12 +170,12 @@ class AFBoardContent extends StatefulWidget { super(key: key); @override - State createState() => _AFBoardContentState(); + State<_AppFlolwyBoardContent> createState() => _AppFlowyBoardContentState(); } -class _AFBoardContentState extends State { +class _AppFlowyBoardContentState extends State<_AppFlolwyBoardContent> { final GlobalKey _boardContentKey = - GlobalKey(debugLabel: '$AFBoardContent overlay key'); + GlobalKey(debugLabel: '$_AppFlolwyBoardContent overlay key'); late BoardOverlayEntry _overlayEntry; final Map _reorderFlexKeys = {}; @@ -263,7 +255,7 @@ class _AFBoardContentState extends State { value: widget.dataController.getGroupController(columnData.id), child: Consumer( builder: (context, value, child) { - final boardColumn = AppFlowyBoardGroupWidget( + final boardColumn = AppFlowyBoardGroup( reorderFlexKey: reorderFlexKey, // key: PageStorageKey(columnData.id), margin: _marginFromIndex(columnIndex), @@ -351,12 +343,12 @@ class BoardGroupContext { class BoardGroupsState extends DraggingStateStorage with ReorderDragTargetIndexKeyStorage { - /// Quick access to the [AppFlowyBoardGroupWidget] + /// Quick access to the [AppFlowyBoardGroup] final Map groupKeys = {}; final Map groupDragStates = {}; final Map> groupDragDragTargets = {}; - void addGroup(String groupId, AppFlowyBoardGroupWidget groupWidget) { + void addGroup(String groupId, AppFlowyBoardGroup groupWidget) { groupKeys[groupId] = groupWidget.reorderFlexKey; } 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 9723f97807..62e6da9bc5 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 @@ -60,9 +60,9 @@ abstract class AppFlowyBoardGroupDataDataSource extends ReoderFlexDataSource { } } -/// [AppFlowyBoardGroupWidget] represents the column of the Board. +/// [AppFlowyBoardGroup] represents the group of the Board. /// -class AppFlowyBoardGroupWidget extends StatefulWidget { +class AppFlowyBoardGroup extends StatefulWidget { final AppFlowyBoardGroupDataDataSource dataSource; final ScrollController? scrollController; final ReorderFlexConfig config; @@ -94,7 +94,7 @@ class AppFlowyBoardGroupWidget extends StatefulWidget { final GlobalObjectKey reorderFlexKey; - const AppFlowyBoardGroupWidget({ + const AppFlowyBoardGroup({ Key? key, required this.reorderFlexKey, this.headerBuilder, @@ -116,13 +116,12 @@ class AppFlowyBoardGroupWidget extends StatefulWidget { super(key: key); @override - State createState() => - _AppFlowyBoardGroupWidgetState(); + State createState() => _AppFlowyBoardGroupState(); } -class _AppFlowyBoardGroupWidgetState extends State { +class _AppFlowyBoardGroupState extends State { final GlobalKey _columnOverlayKey = - GlobalKey(debugLabel: '$AppFlowyBoardGroupWidget overlay key'); + GlobalKey(debugLabel: '$AppFlowyBoardGroup overlay key'); late BoardOverlayEntry _overlayEntry; @override 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 7cd5642791..db23dd845d 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 @@ -28,16 +28,42 @@ typedef OnMoveGroupItemToGroup = void Function( int toIndex, ); +/// A controller for [AppFlowyBoard] widget. +/// +/// A [AppFlowyBoardDataController] can be used to provide an initial value of +/// the board by calling [addGroup] method with the passed in parameter +/// [AppFlowyBoardGroupData]. A [AppFlowyBoardGroupData] represents one +/// group data. Whenever the user modifies the board, this controller will +/// update the corresponding group data. +/// +/// Also, you can register the callbacks that receive the changes. +/// [onMoveGroup] will get called when moving the group from one position to +/// another. +/// +/// [onMoveGroupItem] will get called when moving the group's items. +/// +/// [onMoveGroupItemToGroup] will get called when moving the group's item from +/// one group to another group. class AppFlowyBoardDataController extends ChangeNotifier with EquatableMixin, BoardPhantomControllerDelegate, ReoderFlexDataSource { final List _groupDatas = []; + + /// [onMoveGroup] will get called when moving the group from one position to + /// another. final OnMoveGroup? onMoveGroup; + + /// [onMoveGroupItem] will get called when moving the group's items. final OnMoveGroupItem? onMoveGroupItem; + + /// [onMoveGroupItemToGroup] will get called when moving the group's item from + /// one group to another group. final OnMoveGroupItemToGroup? onMoveGroupItemToGroup; + /// Returns the unmodifiable list of [AppFlowyBoardGroupData] UnmodifiableListView get groupDatas => UnmodifiableListView(_groupDatas); + /// Returns list of group id List get groupIds => _groupDatas.map((groupData) => groupData.id).toList(); @@ -50,6 +76,10 @@ class AppFlowyBoardDataController extends ChangeNotifier this.onMoveGroupItemToGroup, }); + /// Adds a new group to the end of the current group list. + /// + /// If you don't want to notify the listener after adding a new group, the + /// [notify] should set to false. Default value is true. void addGroup(AppFlowyBoardGroupData groupData, {bool notify = true}) { if (_groupControllers[groupData.id] != null) return; @@ -59,6 +89,10 @@ class AppFlowyBoardDataController extends ChangeNotifier if (notify) notifyListeners(); } + /// Adds a list of groups to the end of the current group list. + /// + /// If you don't want to notify the listener after adding the groups, the + /// [notify] should set to false. Default value is true. void addGroups(List groups, {bool notify = true}) { for (final column in groups) { addGroup(column, notify: false); @@ -67,6 +101,10 @@ class AppFlowyBoardDataController extends ChangeNotifier if (groups.isNotEmpty && notify) notifyListeners(); } + /// Removes the group with id [groupId] + /// + /// If you don't want to notify the listener after removing the group, the + /// [notify] should set to false. Default value is true. void removeGroup(String groupId, {bool notify = true}) { final index = _groupDatas.indexWhere((group) => group.id == groupId); if (index == -1) { @@ -82,6 +120,10 @@ class AppFlowyBoardDataController extends ChangeNotifier } } + /// Removes a list of groups + /// + /// If you don't want to notify the listener after removing the groups, the + /// [notify] should set to false. Default value is true. void removeGroups(List groupIds, {bool notify = true}) { for (final groupId in groupIds) { removeGroup(groupId, notify: false); @@ -90,12 +132,16 @@ class AppFlowyBoardDataController extends ChangeNotifier if (groupIds.isNotEmpty && notify) notifyListeners(); } + /// Remove all the groups controller. + /// This method should get called when you want to remove all the current + /// groups or get ready to reinitialize the [AppFlowyBoard]. void clear() { _groupDatas.clear(); _groupControllers.clear(); notifyListeners(); } + /// Returns the [AFBoardGroupDataController] with id [groupId]. AFBoardGroupDataController? getGroupController(String groupId) { final groupController = _groupControllers[groupId]; if (groupController == null) { @@ -105,6 +151,11 @@ class AppFlowyBoardDataController extends ChangeNotifier return groupController; } + /// Moves the group controller from [fromIndex] to [toIndex] and notify the + /// listeners. + /// + /// If you don't want to notify the listener after moving the group, the + /// [notify] should set to false. Default value is true. void moveGroup(int fromIndex, int toIndex, {bool notify = true}) { final toGroupData = _groupDatas[toIndex]; final fromGroupData = _groupDatas.removeAt(fromIndex); @@ -114,31 +165,42 @@ class AppFlowyBoardDataController extends ChangeNotifier if (notify) notifyListeners(); } + /// Moves the group's item from [fromIndex] to [toIndex] + /// If the group with id [groupId] is not exist, this method will do nothing. void moveGroupItem(String groupId, int fromIndex, int toIndex) { if (getGroupController(groupId)?.move(fromIndex, toIndex) ?? false) { onMoveGroupItem?.call(groupId, fromIndex, toIndex); } } + /// Adds the [AppFlowyGroupItem] to the end of the group + /// If the group with id [groupId] is not exist, this method will do nothing. void addGroupItem(String groupId, AppFlowyGroupItem item) { getGroupController(groupId)?.add(item); } + /// Inserts the [AppFlowyGroupItem] at [index] in the group + /// It will do nothing if the group with id [groupId] is not exist void insertGroupItem(String groupId, int index, AppFlowyGroupItem item) { getGroupController(groupId)?.insert(index, item); } + /// Removes the item with id [itemId] from the group + /// It will do nothing if the group with id [groupId] is not exist void removeGroupItem(String groupId, String itemId) { getGroupController(groupId)?.removeWhere((item) => item.id == itemId); } + /// Replaces or inserts the [AppFlowyGroupItem] to the end of the group. + /// If the group with id [groupId] is not exist, this method will do nothing. void updateGroupItem(String groupId, AppFlowyGroupItem item) { getGroupController(groupId)?.replaceOrInsertItem(item); } + /// Swap the @override @protected - void swapGroupItem( + void moveGroupItemToAnotherGroup( String fromGroupId, int fromGroupIndex, String toGroupId, @@ -146,12 +208,12 @@ class AppFlowyBoardDataController extends ChangeNotifier ) { final fromGroupController = getGroupController(fromGroupId)!; final toGroupController = getGroupController(toGroupId)!; - final item = fromGroupController.removeAt(fromGroupIndex); + final fromGroupItem = fromGroupController.removeAt(fromGroupIndex); if (toGroupController.items.length > toGroupIndex) { assert(toGroupController.items[toGroupIndex] is PhantomGroupItem); } - toGroupController.replace(toGroupIndex, item); + toGroupController.replace(toGroupIndex, fromGroupItem); onMoveGroupItemToGroup?.call( fromGroupId, fromGroupIndex, 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 f7b06a73fd..0d505461ed 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 @@ -27,7 +27,7 @@ abstract class BoardPhantomControllerDelegate { /// [dragTargetIndex] the index of the dragTarget void updatePhantom(String groupId, int newIndex); - void swapGroupItem( + void moveGroupItemToAnotherGroup( String fromGroupId, int fromGroupIndex, String toGroupId, @@ -79,7 +79,7 @@ class BoardPhantomController extends OverlapDragTargetDelegate } if (phantomRecord!.toGroupId == groupId) { - delegate.swapGroupItem( + delegate.moveGroupItemToAnotherGroup( fromGroupId, phantomRecord!.fromGroupIndex, toGroupId, From b5321319cc08b5a813a23f9ac7608ec757504c7f Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 6 Sep 2022 11:55:53 +0800 Subject: [PATCH 3/4] chore: fix dart doc warnings --- .../plugins/board/application/board_bloc.dart | 10 +- .../board/presentation/board_page.dart | 14 +-- .../packages/appflowy_board/README.md | 91 +++++++++++--- .../example/lib/multi_board_list_example.dart | 116 ++++++++---------- .../lib/single_board_list_example.dart | 6 +- .../appflowy_board/lib/appflowy_board.dart | 5 +- .../appflowy_board/lib/src/widgets/board.dart | 91 ++++++++------ .../lib/src/widgets/board_data.dart | 44 ++++--- .../group.dart} | 26 ++-- .../group_data.dart} | 45 +++---- .../reorder_flex/drag_target_interceptor.dart | 2 +- .../reorder_phantom/phantom_controller.dart | 8 +- .../lib/src/widgets/styled_widgets/card.dart | 8 +- ...flowy_styled_widgets.dart => widgets.dart} | 0 .../lib/src/widgets/transitions.dart | 1 - .../packages/appflowy_board/pubspec.yaml | 2 +- 16 files changed, 269 insertions(+), 200 deletions(-) rename frontend/app_flowy/packages/appflowy_board/lib/src/widgets/{board_column/board_column.dart => board_group/group.dart} (89%) rename frontend/app_flowy/packages/appflowy_board/lib/src/widgets/{board_column/board_column_data.dart => board_group/group_data.dart} (75%) rename frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/{appflowy_styled_widgets.dart => widgets.dart} (100%) diff --git a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart index faf3490b70..903df92f78 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart @@ -22,7 +22,7 @@ part 'board_bloc.freezed.dart'; class BoardBloc extends Bloc { final BoardDataController _gridDataController; - late final AppFlowyBoardDataController boardController; + late final AppFlowyBoardController boardController; final MoveRowFFIService _rowService; LinkedHashMap groupControllers = LinkedHashMap(); @@ -34,7 +34,7 @@ class BoardBloc extends Bloc { : _rowService = MoveRowFFIService(gridId: view.id), _gridDataController = BoardDataController(view: view), super(BoardState.initial(view.id)) { - boardController = AppFlowyBoardDataController( + boardController = AppFlowyBoardController( onMoveGroup: ( fromColumnId, fromIndex, @@ -165,10 +165,10 @@ class BoardBloc extends Bloc { boardController.clear(); // - List columns = groups + List columns = groups .where((group) => fieldController.getField(group.fieldId) != null) .map((group) { - return AppFlowyBoardGroupData( + return AppFlowyGroupData( id: group.groupId, name: group.desc, items: _buildRows(group), @@ -350,7 +350,7 @@ class BoardColumnItem extends AppFlowyGroupItem { class GroupControllerDelegateImpl extends GroupControllerDelegate { final GridFieldController fieldController; - final AppFlowyBoardDataController controller; + final AppFlowyBoardController controller; final void Function(String, RowPB, int?) onNewColumnItem; GroupControllerDelegateImpl({ diff --git a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart index 35f50dd121..717a5f6f60 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart @@ -63,7 +63,7 @@ class BoardContent extends StatefulWidget { class _BoardContentState extends State { late ScrollController scrollController; - late AFBoardScrollManager scrollManager; + late AppFlowyBoardScrollManager scrollManager; final config = AppFlowyBoardConfig( groupBackgroundColor: HexColor.fromHex('#F7F8FC'), @@ -72,7 +72,7 @@ class _BoardContentState extends State { @override void initState() { scrollController = ScrollController(); - scrollManager = AFBoardScrollManager(); + scrollManager = AppFlowyBoardScrollManager(); super.initState(); } @@ -104,7 +104,7 @@ class _BoardContentState extends State { child: AppFlowyBoard( scrollManager: scrollManager, scrollController: scrollController, - dataController: context.read().boardController, + controller: context.read().boardController, headerBuilder: _buildHeader, footerBuilder: _buildFooter, cardBuilder: (_, column, columnItem) => _buildCard( @@ -149,7 +149,7 @@ class _BoardContentState extends State { Widget _buildHeader( BuildContext context, - AppFlowyBoardGroupData columnData, + AppFlowyGroupData columnData, ) { final boardCustomData = columnData.customData as BoardCustomData; return AppFlowyGroupHeader( @@ -181,7 +181,7 @@ class _BoardContentState extends State { ); } - Widget _buildFooter(BuildContext context, AppFlowyBoardGroupData columnData) { + Widget _buildFooter(BuildContext context, AppFlowyGroupData columnData) { final boardCustomData = columnData.customData as BoardCustomData; final group = boardCustomData.group; @@ -215,7 +215,7 @@ class _BoardContentState extends State { Widget _buildCard( BuildContext context, - AppFlowyBoardGroupData column, + AppFlowyGroupData column, AppFlowyGroupItem columnItem, ) { final boardColumnItem = columnItem as BoardColumnItem; @@ -242,7 +242,7 @@ class _BoardContentState extends State { }, ); - return AppFlowyGroupItemCard( + return AppFlowyGroupCard( key: ValueKey(columnItem.id), margin: config.cardPadding, decoration: _makeBoxDecoration(context), diff --git a/frontend/app_flowy/packages/appflowy_board/README.md b/frontend/app_flowy/packages/appflowy_board/README.md index 7360bde69d..8f54adc14d 100644 --- a/frontend/app_flowy/packages/appflowy_board/README.md +++ b/frontend/app_flowy/packages/appflowy_board/README.md @@ -34,17 +34,83 @@ flutter pub add appflowy_board flutter pub get ``` -This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get): +This will add a line like this to your package's pubspec.yaml: ```dart dependencies: appflowy_board: ^0.0.6 ``` -## Create board +## Create your first board + +Initialize an `AppFlowyBoardController` for the board. It contains the data used by the board. You can +register callbacks to receive the changes of the board. -Import the package in your Dart file: ```dart -import 'package:appflowy_board/appflowy_board.dart'; + +final AppFlowyBoardController controller = AppFlowyBoardController( + onMoveGroup: (fromGroupId, fromIndex, toGroupId, toIndex) { + debugPrint('Move item from $fromIndex to $toIndex'); + }, + onMoveGroupItem: (groupId, fromIndex, toIndex) { + debugPrint('Move $groupId:$fromIndex to $groupId:$toIndex'); + }, + onMoveGroupItemToGroup: (fromGroupId, fromIndex, toGroupId, toIndex) { + debugPrint('Move $fromGroupId:$fromIndex to $toGroupId:$toIndex'); + }, +); +``` + +Provide an initial value of the board by initializing the `AppFlowyGroupData`. It represents a group data and contains list of items. Each item displayed in the group requires to implement the `AppFlowyGroupItem` class. + +```dart + +void initState() { + final group1 = AppFlowyGroupData(id: "To Do", items: [ + TextItem("Card 1"), + TextItem("Card 2"), + ]); + final group2 = AppFlowyGroupData(id: "In Progress", items: [ + TextItem("Card 3"), + TextItem("Card 4"), + ]); + + final group3 = AppFlowyGroupData(id: "Done", items: []); + + controller.addGroup(group1); + controller.addGroup(group2); + controller.addGroup(group3); + super.initState(); +} + +class TextItem extends AppFlowyGroupItem { + final String s; + TextItem(this.s); + + @override + String get id => s; +} + +``` + +Finally, return a `AppFlowyBoard` widget in the build method. + +```dart + +@override +Widget build(BuildContext context) { + return AppFlowyBoard( + controller: controller, + cardBuilder: (context, group, groupItem) { + final textItem = groupItem as TextItem; + return AppFlowyGroupCard( + key: ObjectKey(textItem), + child: Text(textItem.s), + ); + }, + groupConstraints: const BoxConstraints.tightFor(width: 240), + ); +} + ``` ## Usage Example @@ -53,16 +119,14 @@ First, run main.dart to play with the demo. Second, let's delve into multi_board_list_example.dart to understand a few key components: -* A Board widget is created via instantiating an AFBoard() object. -* In the AFBoard() object, you can find: - * AFBoardDataController, which is defined in board_data.dart, is feeded with prepopulated mock data. It also contains callback functions to materialize future user data. - * Three builders: AppFlowyColumnHeader, AppFlowyColumnFooter, AppFlowyColumnItemCard. See below image for what they are used for. +* A Board widget is created via instantiating an `AppFlowyBoard` object. +* In the `AppFlowyBoard` object, you can find the `AppFlowyBoardController`, which is defined in board_data.dart, is feeded with prepopulated mock data. It also contains callback functions to materialize future user data. +* Three builders: AppFlowyBoardHeaderBuilder, AppFlowyBoardFooterBuilder, AppFlowyBoardCardBuilder. See below image for what they are used for. - - +

+ +

## Glossary Please refer to the API documentation. @@ -74,6 +138,3 @@ Please look at [CONTRIBUTING.md](https://appflowy.gitbook.io/docs/essential-docu ## License Distributed under the AGPLv3 License. See [LICENSE](https://github.com/AppFlowy-IO/AppFlowy-Docs/blob/main/LICENSE) for more information. - - -d \ No newline at end of file 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 18f5118ced..8bd7ae98e3 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 @@ -9,22 +9,21 @@ class MultiBoardListExample extends StatefulWidget { } class _MultiBoardListExampleState extends State { - final AppFlowyBoardDataController boardDataController = - AppFlowyBoardDataController( - onMoveGroup: (fromColumnId, fromIndex, toColumnId, toIndex) { - // debugPrint('Move column from $fromIndex to $toIndex'); + final AppFlowyBoardController controller = AppFlowyBoardController( + onMoveGroup: (fromGroupId, fromIndex, toGroupId, toIndex) { + debugPrint('Move item from $fromIndex to $toIndex'); }, - onMoveGroupItem: (columnId, fromIndex, toIndex) { - // debugPrint('Move $columnId:$fromIndex to $columnId:$toIndex'); + onMoveGroupItem: (groupId, fromIndex, toIndex) { + debugPrint('Move $groupId:$fromIndex to $groupId:$toIndex'); }, - onMoveGroupItemToGroup: (fromColumnId, fromIndex, toColumnId, toIndex) { - // debugPrint('Move $fromColumnId:$fromIndex to $toColumnId:$toIndex'); + onMoveGroupItemToGroup: (fromGroupId, fromIndex, toGroupId, toIndex) { + debugPrint('Move $fromGroupId:$fromIndex to $toGroupId:$toIndex'); }, ); @override void initState() { - List a = [ + final group1 = AppFlowyGroupData(id: "To Do", name: "To Do", items: [ TextItem("Card 1"), TextItem("Card 2"), RichTextItem(title: "Card 3", subtitle: 'Aug 1, 2020 4:05 PM'), @@ -34,11 +33,9 @@ class _MultiBoardListExampleState extends State { 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 = - AppFlowyBoardGroupData(id: "To Do", name: "To Do", items: a); - final column2 = AppFlowyBoardGroupData( + final group2 = AppFlowyGroupData( id: "In Progress", name: "In Progress", items: [ @@ -47,12 +44,12 @@ class _MultiBoardListExampleState extends State { ], ); - final column3 = AppFlowyBoardGroupData( + final group3 = AppFlowyGroupData( id: "Done", name: "Done", items: []); - boardDataController.addGroup(column1); - boardDataController.addGroup(column2); - boardDataController.addGroup(column3); + controller.addGroup(group1); + controller.addGroup(group2); + controller.addGroup(group3); super.initState(); } @@ -62,54 +59,45 @@ class _MultiBoardListExampleState extends State { final config = AppFlowyBoardConfig( groupBackgroundColor: HexColor.fromHex('#F7F8FC'), ); - return Container( - color: Colors.white, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 20), - child: AppFlowyBoard( - dataController: boardDataController, - footerBuilder: (context, columnData) { - return AppFlowyGroupFooter( - icon: const Icon(Icons.add, size: 20), - title: const Text('New'), - height: 50, - margin: config.groupItemPadding, - ); - }, - headerBuilder: (context, columnData) { - return AppFlowyGroupHeader( - icon: const Icon(Icons.lightbulb_circle), - title: SizedBox( - width: 60, - child: TextField( - controller: TextEditingController() - ..text = columnData.headerData.groupName, - onSubmitted: (val) { - boardDataController - .getGroupController(columnData.headerData.groupId)! - .updateGroupName(val); - }, - ), + return AppFlowyBoard( + controller: controller, + cardBuilder: (context, group, groupItem) { + return AppFlowyGroupCard( + key: ValueKey(groupItem.id), + child: _buildCard(groupItem), + ); + }, + footerBuilder: (context, columnData) { + return AppFlowyGroupFooter( + icon: const Icon(Icons.add, size: 20), + title: const Text('New'), + height: 50, + margin: config.groupItemPadding, + ); + }, + headerBuilder: (context, columnData) { + return AppFlowyGroupHeader( + icon: const Icon(Icons.lightbulb_circle), + title: SizedBox( + width: 60, + child: TextField( + controller: TextEditingController() + ..text = columnData.headerData.groupName, + onSubmitted: (val) { + controller + .getGroupController(columnData.headerData.groupId)! + .updateGroupName(val); + }, ), - addIcon: const Icon(Icons.add, size: 20), - moreIcon: const Icon(Icons.more_horiz, size: 20), - height: 50, - margin: config.groupItemPadding, - ); - }, - cardBuilder: (context, column, columnItem) { - return AppFlowyGroupItemCard( - key: ValueKey(columnItem.id), - child: _buildCard(columnItem), - ); - }, - groupConstraints: const BoxConstraints.tightFor(width: 240), - config: AppFlowyBoardConfig( - groupBackgroundColor: HexColor.fromHex('#F7F8FC'), - ), - ), - ), - ); + ), + addIcon: const Icon(Icons.add, size: 20), + moreIcon: const Icon(Icons.more_horiz, size: 20), + height: 50, + margin: config.groupItemPadding, + ); + }, + groupConstraints: const BoxConstraints.tightFor(width: 240), + config: config); } Widget _buildCard(AppFlowyGroupItem item) { diff --git a/frontend/app_flowy/packages/appflowy_board/example/lib/single_board_list_example.dart b/frontend/app_flowy/packages/appflowy_board/example/lib/single_board_list_example.dart index 5c68a24e62..c222856efa 100644 --- a/frontend/app_flowy/packages/appflowy_board/example/lib/single_board_list_example.dart +++ b/frontend/app_flowy/packages/appflowy_board/example/lib/single_board_list_example.dart @@ -9,11 +9,11 @@ class SingleBoardListExample extends StatefulWidget { } class _SingleBoardListExampleState extends State { - final AppFlowyBoardDataController boardData = AppFlowyBoardDataController(); + final AppFlowyBoardController boardData = AppFlowyBoardController(); @override void initState() { - final column = AppFlowyBoardGroupData( + final column = AppFlowyGroupData( id: "1", name: "1", items: [ @@ -31,7 +31,7 @@ class _SingleBoardListExampleState extends State { @override Widget build(BuildContext context) { return AppFlowyBoard( - dataController: boardData, + controller: boardData, cardBuilder: (context, column, columnItem) { return _RowWidget( item: columnItem as TextItem, key: ObjectKey(columnItem)); diff --git a/frontend/app_flowy/packages/appflowy_board/lib/appflowy_board.dart b/frontend/app_flowy/packages/appflowy_board/lib/appflowy_board.dart index fc8f3c662f..6125cf29e6 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/appflowy_board.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/appflowy_board.dart @@ -1,6 +1,7 @@ +/// AppFlowyBoard library library appflowy_board; -export 'src/widgets/board_column/board_column_data.dart'; +export 'src/widgets/board_group/group_data.dart'; export 'src/widgets/board_data.dart'; -export 'src/widgets/styled_widgets/appflowy_styled_widgets.dart'; +export 'src/widgets/styled_widgets/widgets.dart'; export 'src/widgets/board.dart'; 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 7e98653848..4c608ecbd0 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 @@ -1,17 +1,17 @@ import 'package:appflowy_board/src/utils/log.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'board_column/board_column.dart'; -import 'board_column/board_column_data.dart'; import 'board_data.dart'; +import 'board_group/group.dart'; +import 'board_group/group_data.dart'; import 'reorder_flex/drag_state.dart'; import 'reorder_flex/drag_target_interceptor.dart'; import 'reorder_flex/reorder_flex.dart'; import 'reorder_phantom/phantom_controller.dart'; import '../rendering/board_overlay.dart'; -class AFBoardScrollManager { - BoardGroupsState? _groupState; +class AppFlowyBoardScrollManager { + AppFlowyBoardState? _groupState; void scrollToBottom(String groupId, VoidCallback? completed) { _groupState @@ -48,26 +48,36 @@ class AppFlowyBoard extends StatelessWidget { final Widget? background; /// The [cardBuilder] function which will be invoked on each card build. - /// The [cardBuilder] takes the [BuildContext],[AppFlowyBoardGroupData] and + /// The [cardBuilder] takes the [BuildContext],[AppFlowyGroupData] and /// the corresponding [AppFlowyGroupItem]. /// /// must return a widget. final AppFlowyBoardCardBuilder cardBuilder; /// The [headerBuilder] function which will be invoked on each group build. - /// The [headerBuilder] takes the [BuildContext] and [AppFlowyBoardGroupData]. + /// The [headerBuilder] takes the [BuildContext] and [AppFlowyGroupData]. /// /// must return a widget. final AppFlowyBoardHeaderBuilder? headerBuilder; /// The [footerBuilder] function which will be invoked on each group build. - /// The [footerBuilder] takes the [BuildContext] and [AppFlowyBoardGroupData]. + /// The [footerBuilder] takes the [BuildContext] and [AppFlowyGroupData]. /// /// must return a widget. final AppFlowyBoardFooterBuilder? footerBuilder; + /// A controller for [AppFlowyBoard] widget. /// - final AppFlowyBoardDataController dataController; + /// A [AppFlowyBoardController] can be used to provide an initial value of + /// the board by calling `addGroup` method with the passed in parameter + /// [AppFlowyGroupData]. A [AppFlowyGroupData] represents one + /// group data. Whenever the user modifies the board, this controller will + /// update the corresponding group data. + /// + /// Also, you can register the callbacks that receive the changes. Check out + /// the [AppFlowyBoardController] for more information. + /// + final AppFlowyBoardController controller; final BoxConstraints groupConstraints; @@ -78,12 +88,12 @@ class AppFlowyBoard extends StatelessWidget { final AppFlowyBoardConfig config; - final AFBoardScrollManager? scrollManager; + final AppFlowyBoardScrollManager? scrollManager; - final BoardGroupsState _groupState = BoardGroupsState(); + final AppFlowyBoardState _groupState = AppFlowyBoardState(); AppFlowyBoard({ - required this.dataController, + required this.controller, required this.cardBuilder, this.background, this.footerBuilder, @@ -95,7 +105,7 @@ class AppFlowyBoard extends StatelessWidget { Key? key, }) : super(key: key) { phantomController = BoardPhantomController( - delegate: dataController, + delegate: controller, groupsState: _groupState, ); } @@ -103,16 +113,16 @@ class AppFlowyBoard extends StatelessWidget { @override Widget build(BuildContext context) { return ChangeNotifierProvider.value( - value: dataController, - child: Consumer( + value: controller, + child: Consumer( builder: (context, notifier, child) { if (scrollManager != null) { scrollManager!._groupState = _groupState; } - return _AppFlolwyBoardContent( + return _AppFlowyBoardContent( config: config, - dataController: dataController, + dataController: controller, scrollController: scrollController, scrollManager: scrollManager, columnsState: _groupState, @@ -123,7 +133,7 @@ class AppFlowyBoard extends StatelessWidget { footerBuilder: footerBuilder, headerBuilder: headerBuilder, phantomController: phantomController, - onReorder: dataController.moveGroup, + onReorder: controller.moveGroup, ); }, ), @@ -131,25 +141,25 @@ class AppFlowyBoard extends StatelessWidget { } } -class _AppFlolwyBoardContent extends StatefulWidget { +class _AppFlowyBoardContent extends StatefulWidget { final ScrollController? scrollController; final OnDragStarted? onDragStarted; final OnReorder onReorder; final OnDragEnded? onDragEnded; - final AppFlowyBoardDataController dataController; + final AppFlowyBoardController dataController; final Widget? background; final AppFlowyBoardConfig config; final ReorderFlexConfig reorderFlexConfig; final BoxConstraints columnConstraints; - final AFBoardScrollManager? scrollManager; - final BoardGroupsState columnsState; + final AppFlowyBoardScrollManager? scrollManager; + final AppFlowyBoardState columnsState; final AppFlowyBoardCardBuilder cardBuilder; final AppFlowyBoardHeaderBuilder? headerBuilder; final AppFlowyBoardFooterBuilder? footerBuilder; final OverlapDragTargetDelegate delegate; final BoardPhantomController phantomController; - const _AppFlolwyBoardContent({ + const _AppFlowyBoardContent({ required this.config, required this.onReorder, required this.delegate, @@ -170,12 +180,12 @@ class _AppFlolwyBoardContent extends StatefulWidget { super(key: key); @override - State<_AppFlolwyBoardContent> createState() => _AppFlowyBoardContentState(); + State<_AppFlowyBoardContent> createState() => _AppFlowyBoardContentState(); } -class _AppFlowyBoardContentState extends State<_AppFlolwyBoardContent> { +class _AppFlowyBoardContentState extends State<_AppFlowyBoardContent> { final GlobalKey _boardContentKey = - GlobalKey(debugLabel: '$_AppFlolwyBoardContent overlay key'); + GlobalKey(debugLabel: '$_AppFlowyBoardContent overlay key'); late BoardOverlayEntry _overlayEntry; final Map _reorderFlexKeys = {}; @@ -253,7 +263,7 @@ class _AppFlowyBoardContentState extends State<_AppFlolwyBoardContent> { return ChangeNotifierProvider.value( key: ValueKey(columnData.id), value: widget.dataController.getGroupController(columnData.id), - child: Consumer( + child: Consumer( builder: (context, value, child) { final boardColumn = AppFlowyBoardGroup( reorderFlexKey: reorderFlexKey, @@ -289,12 +299,12 @@ class _AppFlowyBoardContentState extends State<_AppFlolwyBoardContent> { Widget? _buildHeader( BuildContext context, - AppFlowyBoardGroupData groupData, + AppFlowyGroupData groupData, ) { if (widget.headerBuilder == null) { return null; } - return Selector( + return Selector( selector: (context, controller) => controller.groupData.headerData, builder: (context, headerData, _) { return widget.headerBuilder!(context, groupData)!; @@ -319,9 +329,9 @@ class _AppFlowyBoardContentState extends State<_AppFlolwyBoardContent> { } } -class _BoardGroupDataSourceImpl extends AppFlowyBoardGroupDataDataSource { +class _BoardGroupDataSourceImpl extends AppFlowyGroupDataDataSource { String groupId; - final AppFlowyBoardDataController dataController; + final AppFlowyBoardController dataController; _BoardGroupDataSourceImpl({ required this.groupId, @@ -329,31 +339,34 @@ class _BoardGroupDataSourceImpl extends AppFlowyBoardGroupDataDataSource { }); @override - AppFlowyBoardGroupData get groupData => + AppFlowyGroupData get groupData => dataController.getGroupController(groupId)!.groupData; @override List get acceptedGroupIds => dataController.groupIds; } -class BoardGroupContext { - GlobalKey? groupKey; +/// A context contains the group states including the draggingState. +/// +/// [draggingState] represents the dragging state of the group. +class AppFlowyGroupContext { DraggingState? draggingState; } -class BoardGroupsState extends DraggingStateStorage +class AppFlowyBoardState extends DraggingStateStorage with ReorderDragTargetIndexKeyStorage { - /// Quick access to the [AppFlowyBoardGroup] - final Map groupKeys = {}; + /// Quick access to the [AppFlowyBoardGroup], the [GlobalKey] is bind to the + /// AppFlowyBoardGroup's [ReorderFlex] widget. + final Map groupReorderFlexKeys = {}; final Map groupDragStates = {}; final Map> groupDragDragTargets = {}; void addGroup(String groupId, AppFlowyBoardGroup groupWidget) { - groupKeys[groupId] = groupWidget.reorderFlexKey; + groupReorderFlexKeys[groupId] = groupWidget.reorderFlexKey; } ReorderFlexState? getReorderFlexState({required String groupId}) { - final flexGlobalKey = groupKeys[groupId]; + final flexGlobalKey = groupReorderFlexKeys[groupId]; if (flexGlobalKey == null) return null; if (flexGlobalKey.currentState is! ReorderFlexState) return null; final state = flexGlobalKey.currentState as ReorderFlexState; @@ -361,7 +374,7 @@ class BoardGroupsState extends DraggingStateStorage } ReorderFlex? getReorderFlex({required String groupId}) { - final flexGlobalKey = groupKeys[groupId]; + final flexGlobalKey = groupReorderFlexKeys[groupId]; if (flexGlobalKey == null) return null; if (flexGlobalKey.currentWidget is! ReorderFlex) return null; final widget = flexGlobalKey.currentWidget as ReorderFlex; 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 db23dd845d..9b2222af59 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 @@ -1,9 +1,9 @@ import 'dart:collection'; +import 'package:appflowy_board/src/widgets/board_group/group_data.dart'; import 'package:equatable/equatable.dart'; import '../utils/log.dart'; -import 'board_column/board_column_data.dart'; import 'reorder_flex/reorder_flex.dart'; import 'package:flutter/material.dart'; import 'reorder_phantom/phantom_controller.dart'; @@ -30,9 +30,9 @@ typedef OnMoveGroupItemToGroup = void Function( /// A controller for [AppFlowyBoard] widget. /// -/// A [AppFlowyBoardDataController] can be used to provide an initial value of -/// the board by calling [addGroup] method with the passed in parameter -/// [AppFlowyBoardGroupData]. A [AppFlowyBoardGroupData] represents one +/// A [AppFlowyBoardController] can be used to provide an initial value of +/// the board by calling `addGroup` method with the passed in parameter +/// [AppFlowyGroupData]. A [AppFlowyGroupData] represents one /// group data. Whenever the user modifies the board, this controller will /// update the corresponding group data. /// @@ -44,9 +44,9 @@ typedef OnMoveGroupItemToGroup = void Function( /// /// [onMoveGroupItemToGroup] will get called when moving the group's item from /// one group to another group. -class AppFlowyBoardDataController extends ChangeNotifier +class AppFlowyBoardController extends ChangeNotifier with EquatableMixin, BoardPhantomControllerDelegate, ReoderFlexDataSource { - final List _groupDatas = []; + final List _groupDatas = []; /// [onMoveGroup] will get called when moving the group from one position to /// another. @@ -59,18 +59,18 @@ class AppFlowyBoardDataController extends ChangeNotifier /// one group to another group. final OnMoveGroupItemToGroup? onMoveGroupItemToGroup; - /// Returns the unmodifiable list of [AppFlowyBoardGroupData] - UnmodifiableListView get groupDatas => + /// Returns the unmodifiable list of [AppFlowyGroupData] + UnmodifiableListView get groupDatas => UnmodifiableListView(_groupDatas); /// Returns list of group id List get groupIds => _groupDatas.map((groupData) => groupData.id).toList(); - final LinkedHashMap _groupControllers = + final LinkedHashMap _groupControllers = LinkedHashMap(); - AppFlowyBoardDataController({ + AppFlowyBoardController({ this.onMoveGroup, this.onMoveGroupItem, this.onMoveGroupItemToGroup, @@ -80,10 +80,10 @@ class AppFlowyBoardDataController extends ChangeNotifier /// /// If you don't want to notify the listener after adding a new group, the /// [notify] should set to false. Default value is true. - void addGroup(AppFlowyBoardGroupData groupData, {bool notify = true}) { + void addGroup(AppFlowyGroupData groupData, {bool notify = true}) { if (_groupControllers[groupData.id] != null) return; - final controller = AFBoardGroupDataController(groupData: groupData); + final controller = AppFlowyGroupController(groupData: groupData); _groupDatas.add(groupData); _groupControllers[groupData.id] = controller; if (notify) notifyListeners(); @@ -93,7 +93,7 @@ class AppFlowyBoardDataController extends ChangeNotifier /// /// If you don't want to notify the listener after adding the groups, the /// [notify] should set to false. Default value is true. - void addGroups(List groups, {bool notify = true}) { + void addGroups(List groups, {bool notify = true}) { for (final column in groups) { addGroup(column, notify: false); } @@ -133,6 +133,7 @@ class AppFlowyBoardDataController extends ChangeNotifier } /// Remove all the groups controller. + /// /// This method should get called when you want to remove all the current /// groups or get ready to reinitialize the [AppFlowyBoard]. void clear() { @@ -141,8 +142,8 @@ class AppFlowyBoardDataController extends ChangeNotifier notifyListeners(); } - /// Returns the [AFBoardGroupDataController] with id [groupId]. - AFBoardGroupDataController? getGroupController(String groupId) { + /// Returns the [AppFlowyGroupController] with id [groupId]. + AppFlowyGroupController? getGroupController(String groupId) { final groupController = _groupControllers[groupId]; if (groupController == null) { Log.warn('Group:[$groupId] \'s controller is not exist'); @@ -174,30 +175,35 @@ class AppFlowyBoardDataController extends ChangeNotifier } /// Adds the [AppFlowyGroupItem] to the end of the group + /// /// If the group with id [groupId] is not exist, this method will do nothing. void addGroupItem(String groupId, AppFlowyGroupItem item) { getGroupController(groupId)?.add(item); } /// Inserts the [AppFlowyGroupItem] at [index] in the group + /// /// It will do nothing if the group with id [groupId] is not exist void insertGroupItem(String groupId, int index, AppFlowyGroupItem item) { getGroupController(groupId)?.insert(index, item); } /// Removes the item with id [itemId] from the group + /// /// It will do nothing if the group with id [groupId] is not exist void removeGroupItem(String groupId, String itemId) { getGroupController(groupId)?.removeWhere((item) => item.id == itemId); } /// Replaces or inserts the [AppFlowyGroupItem] to the end of the group. + /// /// If the group with id [groupId] is not exist, this method will do nothing. void updateGroupItem(String groupId, AppFlowyGroupItem item) { getGroupController(groupId)?.replaceOrInsertItem(item); } - /// Swap the + /// Moves the item at [fromGroupIndex] in group with id [fromGroupId] to + /// group with id [toGroupId] at [toGroupIndex] @override @protected void moveGroupItemToAnotherGroup( @@ -228,12 +234,12 @@ class AppFlowyBoardDataController extends ChangeNotifier } @override - AFBoardGroupDataController? controller(String groupId) { + AppFlowyGroupController? controller(String groupId) { return _groupControllers[groupId]; } @override - String get identifier => '$AppFlowyBoardDataController'; + String get identifier => '$AppFlowyBoardController'; @override UnmodifiableListView get items => @@ -253,7 +259,7 @@ class AppFlowyBoardDataController extends ChangeNotifier groupController.removeAt(index); Log.debug( - '[$AppFlowyBoardDataController] Group:[$groupId] remove phantom, current count: ${groupController.items.length}'); + '[$AppFlowyBoardController] Group:[$groupId] remove phantom, current count: ${groupController.items.length}'); } return isExist; } 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_group/group.dart similarity index 89% rename from frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column.dart rename to frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_group/group.dart index 62e6da9bc5..a4b130f6ec 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_group/group.dart @@ -7,40 +7,40 @@ import '../../utils/log.dart'; import '../reorder_phantom/phantom_controller.dart'; import '../reorder_flex/reorder_flex.dart'; import '../reorder_flex/drag_target_interceptor.dart'; -import 'board_column_data.dart'; +import 'group_data.dart'; typedef OnGroupDragStarted = void Function(int index); -typedef OnGroupDragEnded = void Function(String listId); +typedef OnGroupDragEnded = void Function(String groupId); typedef OnGroupReorder = void Function( - String listId, + String groupId, int fromIndex, int toIndex, ); -typedef OnGroupDeleted = void Function(String listId, int deletedIndex); +typedef OnGroupDeleted = void Function(String groupId, int deletedIndex); -typedef OnGroupInserted = void Function(String listId, int insertedIndex); +typedef OnGroupInserted = void Function(String groupId, int insertedIndex); typedef AppFlowyBoardCardBuilder = Widget Function( BuildContext context, - AppFlowyBoardGroupData groupData, + AppFlowyGroupData groupData, AppFlowyGroupItem item, ); typedef AppFlowyBoardHeaderBuilder = Widget? Function( BuildContext context, - AppFlowyBoardGroupData groupData, + AppFlowyGroupData groupData, ); typedef AppFlowyBoardFooterBuilder = Widget Function( BuildContext context, - AppFlowyBoardGroupData groupData, + AppFlowyGroupData groupData, ); -abstract class AppFlowyBoardGroupDataDataSource extends ReoderFlexDataSource { - AppFlowyBoardGroupData get groupData; +abstract class AppFlowyGroupDataDataSource extends ReoderFlexDataSource { + AppFlowyGroupData get groupData; List get acceptedGroupIds; @@ -51,7 +51,7 @@ abstract class AppFlowyBoardGroupDataDataSource extends ReoderFlexDataSource { UnmodifiableListView get items => groupData.items; void debugPrint() { - String msg = '[$AppFlowyBoardGroupDataDataSource] $groupData data: '; + String msg = '[$AppFlowyGroupDataDataSource] $groupData data: '; for (var element in items) { msg = '$msg$element,'; } @@ -60,10 +60,10 @@ abstract class AppFlowyBoardGroupDataDataSource extends ReoderFlexDataSource { } } -/// [AppFlowyBoardGroup] represents the group of the Board. +/// A [AppFlowyBoardGroup] represents the group UI of the Board. /// class AppFlowyBoardGroup extends StatefulWidget { - final AppFlowyBoardGroupDataDataSource dataSource; + final AppFlowyGroupDataDataSource dataSource; final ScrollController? scrollController; final ReorderFlexConfig config; final OnGroupDragStarted? onDragStarted; diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_group/group_data.dart similarity index 75% rename from frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart rename to frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_group/group_data.dart index 1a45dce39b..7bc3bf8657 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_column/board_column_data.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/board_group/group_data.dart @@ -1,10 +1,13 @@ import 'dart:collection'; +import 'package:appflowy_board/src/utils/log.dart'; +import 'package:appflowy_board/src/widgets/reorder_flex/reorder_flex.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; -import '../../utils/log.dart'; -import '../reorder_flex/reorder_flex.dart'; +/// A item represents the generic data model of each group card. +/// +/// Each item displayed in the group required to implement this class. abstract class AppFlowyGroupItem extends ReoderFlexItem { bool get isPhantom => false; @@ -12,7 +15,8 @@ abstract class AppFlowyGroupItem extends ReoderFlexItem { String toString() => id; } -/// [AFBoardGroupDataController] is used to handle the [AppFlowyBoardGroupData]. +/// [AppFlowyGroupController] is used to handle the [AppFlowyGroupData]. +/// /// * Remove an item by calling [removeAt] method. /// * Move item to another position by calling [move] method. /// * Insert item to index by calling [insert] method @@ -20,10 +24,10 @@ abstract class AppFlowyGroupItem extends ReoderFlexItem { /// /// All there operations will notify listeners by default. /// -class AFBoardGroupDataController extends ChangeNotifier with EquatableMixin { - final AppFlowyBoardGroupData groupData; +class AppFlowyGroupController extends ChangeNotifier with EquatableMixin { + final AppFlowyGroupData groupData; - AFBoardGroupDataController({ + AppFlowyGroupController({ required this.groupData, }); @@ -44,12 +48,12 @@ class AFBoardGroupDataController extends ChangeNotifier with EquatableMixin { /// Remove the item at [index]. /// * [index] the index of the item you want to remove /// * [notify] the default value of [notify] is true, it will notify the - /// listener. Set to [false] if you do not want to notify the listeners. + /// listener. Set to false if you do not want to notify the listeners. /// AppFlowyGroupItem removeAt(int index, {bool notify = true}) { assert(index >= 0); - Log.debug('[$AFBoardGroupDataController] $groupData remove item at $index'); + Log.debug('[$AppFlowyGroupController] $groupData remove item at $index'); final item = groupData._items.removeAt(index); if (notify) { notifyListeners(); @@ -74,7 +78,7 @@ class AFBoardGroupDataController extends ChangeNotifier with EquatableMixin { return false; } Log.debug( - '[$AFBoardGroupDataController] $groupData move item from $fromIndex to $toIndex'); + '[$AppFlowyGroupController] $groupData move item from $fromIndex to $toIndex'); final item = groupData._items.removeAt(fromIndex); groupData._items.insert(toIndex, item); notifyListeners(); @@ -87,8 +91,7 @@ class AFBoardGroupDataController extends ChangeNotifier with EquatableMixin { /// The default value of [notify] is true. bool insert(int index, AppFlowyGroupItem item, {bool notify = true}) { assert(index >= 0); - Log.debug( - '[$AFBoardGroupDataController] $groupData insert $item at $index'); + Log.debug('[$AppFlowyGroupController] $groupData insert $item at $index'); if (_containsItem(item)) { return false; @@ -118,7 +121,7 @@ class AFBoardGroupDataController extends ChangeNotifier with EquatableMixin { void replace(int index, AppFlowyGroupItem newItem) { if (groupData._items.isEmpty) { groupData._items.add(newItem); - Log.debug('[$AFBoardGroupDataController] $groupData add $newItem'); + Log.debug('[$AppFlowyGroupController] $groupData add $newItem'); } else { if (index >= groupData._items.length) { return; @@ -127,7 +130,7 @@ class AFBoardGroupDataController extends ChangeNotifier with EquatableMixin { final removedItem = groupData._items.removeAt(index); groupData._items.insert(index, newItem); Log.debug( - '[$AFBoardGroupDataController] $groupData replace $removedItem with $newItem at $index'); + '[$AppFlowyGroupController] $groupData replace $removedItem with $newItem at $index'); } notifyListeners(); @@ -151,22 +154,21 @@ class AFBoardGroupDataController extends ChangeNotifier with EquatableMixin { } } -/// [AppFlowyBoardGroupData] represents the data of each group of the Board. -class AppFlowyBoardGroupData extends ReoderFlexItem - with EquatableMixin { +/// [AppFlowyGroupData] represents the data of each group of the Board. +class AppFlowyGroupData extends ReoderFlexItem with EquatableMixin { @override final String id; - AppFlowyBoardGroupHeaderData headerData; + AppFlowyGroupHeaderData headerData; final List _items; final CustomData? customData; - AppFlowyBoardGroupData({ + AppFlowyGroupData({ this.customData, required this.id, required String name, List items = const [], }) : _items = items, - headerData = AppFlowyBoardGroupHeaderData( + headerData = AppFlowyGroupHeaderData( groupId: id, groupName: name, ); @@ -184,10 +186,9 @@ class AppFlowyBoardGroupData extends ReoderFlexItem } } -class AppFlowyBoardGroupHeaderData { +class AppFlowyGroupHeaderData { String groupId; String groupName; - AppFlowyBoardGroupHeaderData( - {required this.groupId, required this.groupName}); + AppFlowyGroupHeaderData({required this.groupId, required this.groupName}); } 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 97aba2c294..bce94502bd 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 @@ -55,7 +55,7 @@ class OverlappingDragTargetInterceptor extends DragTargetInterceptor { final String reorderFlexId; final List acceptedReorderFlexId; final OverlapDragTargetDelegate delegate; - final BoardGroupsState columnsState; + final AppFlowyBoardState columnsState; Timer? _delayOperation; OverlappingDragTargetInterceptor({ 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 0d505461ed..29c469c4a1 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 @@ -8,14 +8,14 @@ import '../reorder_flex/drag_target_interceptor.dart'; import 'phantom_state.dart'; abstract class BoardPhantomControllerDelegate { - AFBoardGroupDataController? controller(String groupId); + AppFlowyGroupController? controller(String groupId); bool removePhantom(String groupId); /// Insert the phantom into the group /// /// * [groupId] id of the group - /// * [phantomIndex] the phantom occupies index + /// * [index] the phantom occupies index void insertPhantom( String groupId, int index, @@ -24,7 +24,7 @@ abstract class BoardPhantomControllerDelegate { /// Update the group's phantom index if it exists. /// [toGroupId] the id of the group - /// [dragTargetIndex] the index of the dragTarget + /// [newIndex] the index of the dragTarget void updatePhantom(String groupId, int newIndex); void moveGroupItemToAnotherGroup( @@ -39,7 +39,7 @@ class BoardPhantomController extends OverlapDragTargetDelegate with CrossReorderFlexDragTargetDelegate { PhantomRecord? phantomRecord; final BoardPhantomControllerDelegate delegate; - final BoardGroupsState groupsState; + final AppFlowyBoardState groupsState; final phantomState = GroupPhantomState(); BoardPhantomController({ required this.delegate, diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/card.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/card.dart index 61822efbde..b3ae96b28e 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/card.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/card.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; -class AppFlowyGroupItemCard extends StatefulWidget { +class AppFlowyGroupCard extends StatefulWidget { final Widget? child; final EdgeInsets margin; final BoxConstraints boxConstraints; final BoxDecoration decoration; - const AppFlowyGroupItemCard({ + const AppFlowyGroupCard({ this.child, this.margin = const EdgeInsets.all(4), this.decoration = const BoxDecoration( @@ -18,10 +18,10 @@ class AppFlowyGroupItemCard extends StatefulWidget { }) : super(key: key); @override - State createState() => _AppFlowyGroupItemCardState(); + State createState() => _AppFlowyGroupCardState(); } -class _AppFlowyGroupItemCardState extends State { +class _AppFlowyGroupCardState extends State { @override Widget build(BuildContext context) { return Padding( diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/appflowy_styled_widgets.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/widgets.dart similarity index 100% rename from frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/appflowy_styled_widgets.dart rename to frontend/app_flowy/packages/appflowy_board/lib/src/widgets/styled_widgets/widgets.dart diff --git a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/transitions.dart b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/transitions.dart index 525006af9c..d5cb1de26a 100644 --- a/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/transitions.dart +++ b/frontend/app_flowy/packages/appflowy_board/lib/src/widgets/transitions.dart @@ -1,5 +1,4 @@ import 'package:flutter/widgets.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/rendering.dart'; class SizeTransitionWithIntrinsicSize extends SingleChildRenderObjectWidget { diff --git a/frontend/app_flowy/packages/appflowy_board/pubspec.yaml b/frontend/app_flowy/packages/appflowy_board/pubspec.yaml index 14dc501dcc..e4f86ad642 100644 --- a/frontend/app_flowy/packages/appflowy_board/pubspec.yaml +++ b/frontend/app_flowy/packages/appflowy_board/pubspec.yaml @@ -1,5 +1,5 @@ name: appflowy_board -description: AppFlowy board implementation. +description: AppFlowyBoard is a board-style widget that consists of multi-groups. It supports drag and drop between different groups. version: 0.0.6 homepage: https://github.com/AppFlowy-IO/AppFlowy repository: https://github.com/AppFlowy-IO/AppFlowy/tree/main/frontend/app_flowy/packages/appflowy_board From a21050b5941ec636c46ccf8c75d0f5a21fbe3ac8 Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 6 Sep 2022 14:25:39 +0800 Subject: [PATCH 4/4] chore: update appflowy_baord documentation --- .../board/presentation/board_page.dart | 11 ++--- .../packages/appflowy_board/CHANGELOG.md | 3 ++ .../packages/appflowy_board/README.md | 2 +- .../appflowy_board/lib/src/widgets/board.dart | 46 ++++++++++--------- .../packages/appflowy_board/pubspec.yaml | 2 +- frontend/app_flowy/pubspec.lock | 2 +- 6 files changed, 34 insertions(+), 32 deletions(-) diff --git a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart index 717a5f6f60..d40a2f5ea9 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart @@ -62,8 +62,7 @@ class BoardContent extends StatefulWidget { } class _BoardContentState extends State { - late ScrollController scrollController; - late AppFlowyBoardScrollManager scrollManager; + late AppFlowyBoardScrollController scrollManager; final config = AppFlowyBoardConfig( groupBackgroundColor: HexColor.fromHex('#F7F8FC'), @@ -71,8 +70,7 @@ class _BoardContentState extends State { @override void initState() { - scrollController = ScrollController(); - scrollManager = AppFlowyBoardScrollManager(); + scrollManager = AppFlowyBoardScrollController(); super.initState(); } @@ -102,8 +100,8 @@ class _BoardContentState extends State { Expanded _buildBoard(BuildContext context) { return Expanded( child: AppFlowyBoard( - scrollManager: scrollManager, - scrollController: scrollController, + boardScrollController: scrollManager, + scrollController: ScrollController(), controller: context.read().boardController, headerBuilder: _buildHeader, footerBuilder: _buildFooter, @@ -143,7 +141,6 @@ class _BoardContentState extends State { @override void dispose() { - scrollController.dispose(); super.dispose(); } diff --git a/frontend/app_flowy/packages/appflowy_board/CHANGELOG.md b/frontend/app_flowy/packages/appflowy_board/CHANGELOG.md index d8eceeefee..56115c698b 100644 --- a/frontend/app_flowy/packages/appflowy_board/CHANGELOG.md +++ b/frontend/app_flowy/packages/appflowy_board/CHANGELOG.md @@ -1,3 +1,6 @@ +# 0.0.7 +* Rename some classes +* Add documentation # 0.0.6 * Support scroll to bottom * Fix some bugs diff --git a/frontend/app_flowy/packages/appflowy_board/README.md b/frontend/app_flowy/packages/appflowy_board/README.md index 8f54adc14d..7d879a491b 100644 --- a/frontend/app_flowy/packages/appflowy_board/README.md +++ b/frontend/app_flowy/packages/appflowy_board/README.md @@ -120,7 +120,7 @@ First, run main.dart to play with the demo. Second, let's delve into multi_board_list_example.dart to understand a few key components: * A Board widget is created via instantiating an `AppFlowyBoard` object. -* In the `AppFlowyBoard` object, you can find the `AppFlowyBoardController`, which is defined in board_data.dart, is feeded with prepopulated mock data. It also contains callback functions to materialize future user data. +* In the `AppFlowyBoard` object, you can find the `AppFlowyBoardController`, which is defined in board_data.dart, is fed with pre-populated mock data. It also contains callback functions to materialize future user data. * Three builders: AppFlowyBoardHeaderBuilder, AppFlowyBoardFooterBuilder, AppFlowyBoardCardBuilder. See below image for what they are used for. 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 4c608ecbd0..4a71595ea6 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 @@ -10,7 +10,7 @@ import 'reorder_flex/reorder_flex.dart'; import 'reorder_phantom/phantom_controller.dart'; import '../rendering/board_overlay.dart'; -class AppFlowyBoardScrollManager { +class AppFlowyBoardScrollController { AppFlowyBoardState? _groupState; void scrollToBottom(String groupId, VoidCallback? completed) { @@ -79,19 +79,27 @@ class AppFlowyBoard extends StatelessWidget { /// final AppFlowyBoardController controller; + /// A constraints applied to [AppFlowyBoardGroup] widget. final BoxConstraints groupConstraints; + /// A controller is used by the [ReorderFlex]. /// - late final BoardPhantomController phantomController; - + /// The [ReorderFlex] will used the primary scrollController of the current + /// [BuildContext] by using PrimaryScrollController.of(context). + /// If the primary scrollController is null, we will assign a new [ScrollController]. final ScrollController? scrollController; + /// final AppFlowyBoardConfig config; - final AppFlowyBoardScrollManager? scrollManager; + /// A controller is used to control each group scroll actions. + /// + final AppFlowyBoardScrollController? boardScrollController; final AppFlowyBoardState _groupState = AppFlowyBoardState(); + late final BoardPhantomController _phantomController; + AppFlowyBoard({ required this.controller, required this.cardBuilder, @@ -99,12 +107,12 @@ class AppFlowyBoard extends StatelessWidget { this.footerBuilder, this.headerBuilder, this.scrollController, - this.scrollManager, + this.boardScrollController, this.groupConstraints = const BoxConstraints(maxWidth: 200), this.config = const AppFlowyBoardConfig(), Key? key, }) : super(key: key) { - phantomController = BoardPhantomController( + _phantomController = BoardPhantomController( delegate: controller, groupsState: _groupState, ); @@ -116,23 +124,23 @@ class AppFlowyBoard extends StatelessWidget { value: controller, child: Consumer( builder: (context, notifier, child) { - if (scrollManager != null) { - scrollManager!._groupState = _groupState; + if (boardScrollController != null) { + boardScrollController!._groupState = _groupState; } return _AppFlowyBoardContent( config: config, dataController: controller, scrollController: scrollController, - scrollManager: scrollManager, + scrollManager: boardScrollController, columnsState: _groupState, background: background, - delegate: phantomController, - columnConstraints: groupConstraints, + delegate: _phantomController, + groupConstraints: groupConstraints, cardBuilder: cardBuilder, footerBuilder: footerBuilder, headerBuilder: headerBuilder, - phantomController: phantomController, + phantomController: _phantomController, onReorder: controller.moveGroup, ); }, @@ -143,15 +151,13 @@ class AppFlowyBoard extends StatelessWidget { class _AppFlowyBoardContent extends StatefulWidget { final ScrollController? scrollController; - final OnDragStarted? onDragStarted; final OnReorder onReorder; - final OnDragEnded? onDragEnded; final AppFlowyBoardController dataController; final Widget? background; final AppFlowyBoardConfig config; final ReorderFlexConfig reorderFlexConfig; - final BoxConstraints columnConstraints; - final AppFlowyBoardScrollManager? scrollManager; + final BoxConstraints groupConstraints; + final AppFlowyBoardScrollController? scrollManager; final AppFlowyBoardState columnsState; final AppFlowyBoardCardBuilder cardBuilder; final AppFlowyBoardHeaderBuilder? headerBuilder; @@ -166,11 +172,9 @@ class _AppFlowyBoardContent extends StatefulWidget { required this.dataController, required this.scrollManager, required this.columnsState, - this.onDragStarted, - this.onDragEnded, this.scrollController, this.background, - required this.columnConstraints, + required this.groupConstraints, required this.cardBuilder, this.footerBuilder, this.headerBuilder, @@ -204,9 +208,7 @@ class _AppFlowyBoardContentState extends State<_AppFlowyBoardContent> { final reorderFlex = ReorderFlex( config: widget.reorderFlexConfig, scrollController: widget.scrollController, - onDragStarted: widget.onDragStarted, onReorder: widget.onReorder, - onDragEnded: widget.onDragEnded, dataSource: widget.dataController, direction: Axis.horizontal, interceptor: interceptor, @@ -285,7 +287,7 @@ class _AppFlowyBoardContentState extends State<_AppFlowyBoardContent> { widget.columnsState.addGroup(columnData.id, boardColumn); return ConstrainedBox( - constraints: widget.columnConstraints, + constraints: widget.groupConstraints, child: boardColumn, ); }, diff --git a/frontend/app_flowy/packages/appflowy_board/pubspec.yaml b/frontend/app_flowy/packages/appflowy_board/pubspec.yaml index e4f86ad642..90907edca5 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: AppFlowyBoard is a board-style widget that consists of multi-groups. It supports drag and drop between different groups. -version: 0.0.6 +version: 0.0.7 homepage: https://github.com/AppFlowy-IO/AppFlowy repository: https://github.com/AppFlowy-IO/AppFlowy/tree/main/frontend/app_flowy/packages/appflowy_board diff --git a/frontend/app_flowy/pubspec.lock b/frontend/app_flowy/pubspec.lock index 8b8b9cfb05..693c6b41e9 100644 --- a/frontend/app_flowy/pubspec.lock +++ b/frontend/app_flowy/pubspec.lock @@ -28,7 +28,7 @@ packages: path: "packages/appflowy_board" relative: true source: path - version: "0.0.6" + version: "0.0.7" appflowy_editor: dependency: "direct main" description: