chore: fix dart doc warnings

This commit is contained in:
appflowy 2022-09-06 11:55:53 +08:00
parent 8f5569a012
commit b5321319cc
16 changed files with 269 additions and 200 deletions

View File

@ -22,7 +22,7 @@ part 'board_bloc.freezed.dart';
class BoardBloc extends Bloc<BoardEvent, BoardState> {
final BoardDataController _gridDataController;
late final AppFlowyBoardDataController boardController;
late final AppFlowyBoardController boardController;
final MoveRowFFIService _rowService;
LinkedHashMap<String, GroupController> groupControllers = LinkedHashMap();
@ -34,7 +34,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
: _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<BoardEvent, BoardState> {
boardController.clear();
//
List<AppFlowyBoardGroupData> columns = groups
List<AppFlowyGroupData> 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({

View File

@ -63,7 +63,7 @@ class BoardContent extends StatefulWidget {
class _BoardContentState extends State<BoardContent> {
late ScrollController scrollController;
late AFBoardScrollManager scrollManager;
late AppFlowyBoardScrollManager scrollManager;
final config = AppFlowyBoardConfig(
groupBackgroundColor: HexColor.fromHex('#F7F8FC'),
@ -72,7 +72,7 @@ class _BoardContentState extends State<BoardContent> {
@override
void initState() {
scrollController = ScrollController();
scrollManager = AFBoardScrollManager();
scrollManager = AppFlowyBoardScrollManager();
super.initState();
}
@ -104,7 +104,7 @@ class _BoardContentState extends State<BoardContent> {
child: AppFlowyBoard(
scrollManager: scrollManager,
scrollController: scrollController,
dataController: context.read<BoardBloc>().boardController,
controller: context.read<BoardBloc>().boardController,
headerBuilder: _buildHeader,
footerBuilder: _buildFooter,
cardBuilder: (_, column, columnItem) => _buildCard(
@ -149,7 +149,7 @@ class _BoardContentState extends State<BoardContent> {
Widget _buildHeader(
BuildContext context,
AppFlowyBoardGroupData columnData,
AppFlowyGroupData columnData,
) {
final boardCustomData = columnData.customData as BoardCustomData;
return AppFlowyGroupHeader(
@ -181,7 +181,7 @@ class _BoardContentState extends State<BoardContent> {
);
}
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<BoardContent> {
Widget _buildCard(
BuildContext context,
AppFlowyBoardGroupData column,
AppFlowyGroupData column,
AppFlowyGroupItem columnItem,
) {
final boardColumnItem = columnItem as BoardColumnItem;
@ -242,7 +242,7 @@ class _BoardContentState extends State<BoardContent> {
},
);
return AppFlowyGroupItemCard(
return AppFlowyGroupCard(
key: ValueKey(columnItem.id),
margin: config.cardPadding,
decoration: _makeBoxDecoration(context),

View File

@ -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.
<!-- <p>
<img src="https://github.com/AppFlowy-IO/AppFlowy/blob/main/frontend/app_flowy/packages/appflowy_board/example/gifs/appflowy_board_builders.jpg?raw=true" width="100%" title="AppFlowyBoard">
</p> -->
<p>
<img src="https://github.com/AppFlowy-IO/AppFlowy/blob/main/frontend/app_flowy/packages/appflowy_board/example/gifs/appflowy_board_builders.jpg?raw=true" width="200" title="AppFlowyBoard">
</p>
## 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

View File

@ -9,22 +9,21 @@ class MultiBoardListExample extends StatefulWidget {
}
class _MultiBoardListExampleState extends State<MultiBoardListExample> {
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<AppFlowyGroupItem> 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<MultiBoardListExample> {
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: <AppFlowyGroupItem>[
@ -47,12 +44,12 @@ class _MultiBoardListExampleState extends State<MultiBoardListExample> {
],
);
final column3 = AppFlowyBoardGroupData(
final group3 = AppFlowyGroupData(
id: "Done", name: "Done", items: <AppFlowyGroupItem>[]);
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<MultiBoardListExample> {
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) {

View File

@ -9,11 +9,11 @@ class SingleBoardListExample extends StatefulWidget {
}
class _SingleBoardListExampleState extends State<SingleBoardListExample> {
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<SingleBoardListExample> {
@override
Widget build(BuildContext context) {
return AppFlowyBoard(
dataController: boardData,
controller: boardData,
cardBuilder: (context, column, columnItem) {
return _RowWidget(
item: columnItem as TextItem, key: ObjectKey(columnItem));

View File

@ -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';

View File

@ -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<AppFlowyBoardDataController>(
value: controller,
child: Consumer<AppFlowyBoardController>(
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<String, GlobalObjectKey> _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<AFBoardGroupDataController>(
child: Consumer<AppFlowyGroupController>(
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<AFBoardGroupDataController, AppFlowyBoardGroupHeaderData>(
return Selector<AppFlowyGroupController, AppFlowyGroupHeaderData>(
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<String> 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<String, GlobalKey> groupKeys = {};
/// Quick access to the [AppFlowyBoardGroup], the [GlobalKey] is bind to the
/// AppFlowyBoardGroup's [ReorderFlex] widget.
final Map<String, GlobalKey> groupReorderFlexKeys = {};
final Map<String, DraggingState> groupDragStates = {};
final Map<String, Map<String, GlobalObjectKey>> 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;

View File

@ -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<AppFlowyBoardGroupData> _groupDatas = [];
final List<AppFlowyGroupData> _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<AppFlowyBoardGroupData> get groupDatas =>
/// Returns the unmodifiable list of [AppFlowyGroupData]
UnmodifiableListView<AppFlowyGroupData> get groupDatas =>
UnmodifiableListView(_groupDatas);
/// Returns list of group id
List<String> get groupIds =>
_groupDatas.map((groupData) => groupData.id).toList();
final LinkedHashMap<String, AFBoardGroupDataController> _groupControllers =
final LinkedHashMap<String, AppFlowyGroupController> _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<AppFlowyBoardGroupData> groups, {bool notify = true}) {
void addGroups(List<AppFlowyGroupData> 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<ReoderFlexItem> 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;
}

View File

@ -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<String> get acceptedGroupIds;
@ -51,7 +51,7 @@ abstract class AppFlowyBoardGroupDataDataSource extends ReoderFlexDataSource {
UnmodifiableListView<AppFlowyGroupItem> 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;

View File

@ -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<CustomData> extends ReoderFlexItem
with EquatableMixin {
/// [AppFlowyGroupData] represents the data of each group of the Board.
class AppFlowyGroupData<CustomData> extends ReoderFlexItem with EquatableMixin {
@override
final String id;
AppFlowyBoardGroupHeaderData headerData;
AppFlowyGroupHeaderData headerData;
final List<AppFlowyGroupItem> _items;
final CustomData? customData;
AppFlowyBoardGroupData({
AppFlowyGroupData({
this.customData,
required this.id,
required String name,
List<AppFlowyGroupItem> items = const [],
}) : _items = items,
headerData = AppFlowyBoardGroupHeaderData(
headerData = AppFlowyGroupHeaderData(
groupId: id,
groupName: name,
);
@ -184,10 +186,9 @@ class AppFlowyBoardGroupData<CustomData> extends ReoderFlexItem
}
}
class AppFlowyBoardGroupHeaderData {
class AppFlowyGroupHeaderData {
String groupId;
String groupName;
AppFlowyBoardGroupHeaderData(
{required this.groupId, required this.groupName});
AppFlowyGroupHeaderData({required this.groupId, required this.groupName});
}

View File

@ -55,7 +55,7 @@ class OverlappingDragTargetInterceptor extends DragTargetInterceptor {
final String reorderFlexId;
final List<String> acceptedReorderFlexId;
final OverlapDragTargetDelegate delegate;
final BoardGroupsState columnsState;
final AppFlowyBoardState columnsState;
Timer? _delayOperation;
OverlappingDragTargetInterceptor({

View File

@ -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,

View File

@ -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<AppFlowyGroupItemCard> createState() => _AppFlowyGroupItemCardState();
State<AppFlowyGroupCard> createState() => _AppFlowyGroupCardState();
}
class _AppFlowyGroupItemCardState extends State<AppFlowyGroupItemCard> {
class _AppFlowyGroupCardState extends State<AppFlowyGroupCard> {
@override
Widget build(BuildContext context) {
return Padding(

View File

@ -1,5 +1,4 @@
import 'package:flutter/widgets.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
class SizeTransitionWithIntrinsicSize extends SingleChildRenderObjectWidget {

View File

@ -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