From b5321319cc08b5a813a23f9ac7608ec757504c7f Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 6 Sep 2022 11:55:53 +0800 Subject: [PATCH] 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