mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: fix dart doc warnings
This commit is contained in:
parent
8f5569a012
commit
b5321319cc
@ -22,7 +22,7 @@ part 'board_bloc.freezed.dart';
|
|||||||
|
|
||||||
class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
||||||
final BoardDataController _gridDataController;
|
final BoardDataController _gridDataController;
|
||||||
late final AppFlowyBoardDataController boardController;
|
late final AppFlowyBoardController boardController;
|
||||||
final MoveRowFFIService _rowService;
|
final MoveRowFFIService _rowService;
|
||||||
LinkedHashMap<String, GroupController> groupControllers = LinkedHashMap();
|
LinkedHashMap<String, GroupController> groupControllers = LinkedHashMap();
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
: _rowService = MoveRowFFIService(gridId: view.id),
|
: _rowService = MoveRowFFIService(gridId: view.id),
|
||||||
_gridDataController = BoardDataController(view: view),
|
_gridDataController = BoardDataController(view: view),
|
||||||
super(BoardState.initial(view.id)) {
|
super(BoardState.initial(view.id)) {
|
||||||
boardController = AppFlowyBoardDataController(
|
boardController = AppFlowyBoardController(
|
||||||
onMoveGroup: (
|
onMoveGroup: (
|
||||||
fromColumnId,
|
fromColumnId,
|
||||||
fromIndex,
|
fromIndex,
|
||||||
@ -165,10 +165,10 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
boardController.clear();
|
boardController.clear();
|
||||||
|
|
||||||
//
|
//
|
||||||
List<AppFlowyBoardGroupData> columns = groups
|
List<AppFlowyGroupData> columns = groups
|
||||||
.where((group) => fieldController.getField(group.fieldId) != null)
|
.where((group) => fieldController.getField(group.fieldId) != null)
|
||||||
.map((group) {
|
.map((group) {
|
||||||
return AppFlowyBoardGroupData(
|
return AppFlowyGroupData(
|
||||||
id: group.groupId,
|
id: group.groupId,
|
||||||
name: group.desc,
|
name: group.desc,
|
||||||
items: _buildRows(group),
|
items: _buildRows(group),
|
||||||
@ -350,7 +350,7 @@ class BoardColumnItem extends AppFlowyGroupItem {
|
|||||||
|
|
||||||
class GroupControllerDelegateImpl extends GroupControllerDelegate {
|
class GroupControllerDelegateImpl extends GroupControllerDelegate {
|
||||||
final GridFieldController fieldController;
|
final GridFieldController fieldController;
|
||||||
final AppFlowyBoardDataController controller;
|
final AppFlowyBoardController controller;
|
||||||
final void Function(String, RowPB, int?) onNewColumnItem;
|
final void Function(String, RowPB, int?) onNewColumnItem;
|
||||||
|
|
||||||
GroupControllerDelegateImpl({
|
GroupControllerDelegateImpl({
|
||||||
|
@ -63,7 +63,7 @@ class BoardContent extends StatefulWidget {
|
|||||||
|
|
||||||
class _BoardContentState extends State<BoardContent> {
|
class _BoardContentState extends State<BoardContent> {
|
||||||
late ScrollController scrollController;
|
late ScrollController scrollController;
|
||||||
late AFBoardScrollManager scrollManager;
|
late AppFlowyBoardScrollManager scrollManager;
|
||||||
|
|
||||||
final config = AppFlowyBoardConfig(
|
final config = AppFlowyBoardConfig(
|
||||||
groupBackgroundColor: HexColor.fromHex('#F7F8FC'),
|
groupBackgroundColor: HexColor.fromHex('#F7F8FC'),
|
||||||
@ -72,7 +72,7 @@ class _BoardContentState extends State<BoardContent> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
scrollController = ScrollController();
|
scrollController = ScrollController();
|
||||||
scrollManager = AFBoardScrollManager();
|
scrollManager = AppFlowyBoardScrollManager();
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ class _BoardContentState extends State<BoardContent> {
|
|||||||
child: AppFlowyBoard(
|
child: AppFlowyBoard(
|
||||||
scrollManager: scrollManager,
|
scrollManager: scrollManager,
|
||||||
scrollController: scrollController,
|
scrollController: scrollController,
|
||||||
dataController: context.read<BoardBloc>().boardController,
|
controller: context.read<BoardBloc>().boardController,
|
||||||
headerBuilder: _buildHeader,
|
headerBuilder: _buildHeader,
|
||||||
footerBuilder: _buildFooter,
|
footerBuilder: _buildFooter,
|
||||||
cardBuilder: (_, column, columnItem) => _buildCard(
|
cardBuilder: (_, column, columnItem) => _buildCard(
|
||||||
@ -149,7 +149,7 @@ class _BoardContentState extends State<BoardContent> {
|
|||||||
|
|
||||||
Widget _buildHeader(
|
Widget _buildHeader(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
AppFlowyBoardGroupData columnData,
|
AppFlowyGroupData columnData,
|
||||||
) {
|
) {
|
||||||
final boardCustomData = columnData.customData as BoardCustomData;
|
final boardCustomData = columnData.customData as BoardCustomData;
|
||||||
return AppFlowyGroupHeader(
|
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 boardCustomData = columnData.customData as BoardCustomData;
|
||||||
final group = boardCustomData.group;
|
final group = boardCustomData.group;
|
||||||
|
|
||||||
@ -215,7 +215,7 @@ class _BoardContentState extends State<BoardContent> {
|
|||||||
|
|
||||||
Widget _buildCard(
|
Widget _buildCard(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
AppFlowyBoardGroupData column,
|
AppFlowyGroupData column,
|
||||||
AppFlowyGroupItem columnItem,
|
AppFlowyGroupItem columnItem,
|
||||||
) {
|
) {
|
||||||
final boardColumnItem = columnItem as BoardColumnItem;
|
final boardColumnItem = columnItem as BoardColumnItem;
|
||||||
@ -242,7 +242,7 @@ class _BoardContentState extends State<BoardContent> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return AppFlowyGroupItemCard(
|
return AppFlowyGroupCard(
|
||||||
key: ValueKey(columnItem.id),
|
key: ValueKey(columnItem.id),
|
||||||
margin: config.cardPadding,
|
margin: config.cardPadding,
|
||||||
decoration: _makeBoxDecoration(context),
|
decoration: _makeBoxDecoration(context),
|
||||||
|
@ -34,17 +34,83 @@ flutter pub add appflowy_board
|
|||||||
flutter pub get
|
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
|
```dart
|
||||||
dependencies:
|
dependencies:
|
||||||
appflowy_board: ^0.0.6
|
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
|
```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
|
## 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:
|
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.
|
* A Board widget is created via instantiating an `AppFlowyBoard` object.
|
||||||
* In the AFBoard() object, you can find:
|
* 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.
|
||||||
* 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: AppFlowyBoardHeaderBuilder, AppFlowyBoardFooterBuilder, AppFlowyBoardCardBuilder. See below image for what they are used for.
|
||||||
* Three builders: AppFlowyColumnHeader, AppFlowyColumnFooter, AppFlowyColumnItemCard. See below image for what they are used for.
|
|
||||||
|
|
||||||
|
|
||||||
|
<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">
|
||||||
<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> -->
|
|
||||||
|
|
||||||
## Glossary
|
## Glossary
|
||||||
Please refer to the API documentation.
|
Please refer to the API documentation.
|
||||||
@ -74,6 +138,3 @@ Please look at [CONTRIBUTING.md](https://appflowy.gitbook.io/docs/essential-docu
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
Distributed under the AGPLv3 License. See [LICENSE](https://github.com/AppFlowy-IO/AppFlowy-Docs/blob/main/LICENSE) for more information.
|
Distributed under the AGPLv3 License. See [LICENSE](https://github.com/AppFlowy-IO/AppFlowy-Docs/blob/main/LICENSE) for more information.
|
||||||
|
|
||||||
|
|
||||||
d
|
|
@ -9,22 +9,21 @@ class MultiBoardListExample extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _MultiBoardListExampleState extends State<MultiBoardListExample> {
|
class _MultiBoardListExampleState extends State<MultiBoardListExample> {
|
||||||
final AppFlowyBoardDataController boardDataController =
|
final AppFlowyBoardController controller = AppFlowyBoardController(
|
||||||
AppFlowyBoardDataController(
|
onMoveGroup: (fromGroupId, fromIndex, toGroupId, toIndex) {
|
||||||
onMoveGroup: (fromColumnId, fromIndex, toColumnId, toIndex) {
|
debugPrint('Move item from $fromIndex to $toIndex');
|
||||||
// debugPrint('Move column from $fromIndex to $toIndex');
|
|
||||||
},
|
},
|
||||||
onMoveGroupItem: (columnId, fromIndex, toIndex) {
|
onMoveGroupItem: (groupId, fromIndex, toIndex) {
|
||||||
// debugPrint('Move $columnId:$fromIndex to $columnId:$toIndex');
|
debugPrint('Move $groupId:$fromIndex to $groupId:$toIndex');
|
||||||
},
|
},
|
||||||
onMoveGroupItemToGroup: (fromColumnId, fromIndex, toColumnId, toIndex) {
|
onMoveGroupItemToGroup: (fromGroupId, fromIndex, toGroupId, toIndex) {
|
||||||
// debugPrint('Move $fromColumnId:$fromIndex to $toColumnId:$toIndex');
|
debugPrint('Move $fromGroupId:$fromIndex to $toGroupId:$toIndex');
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
List<AppFlowyGroupItem> a = [
|
final group1 = AppFlowyGroupData(id: "To Do", name: "To Do", items: [
|
||||||
TextItem("Card 1"),
|
TextItem("Card 1"),
|
||||||
TextItem("Card 2"),
|
TextItem("Card 2"),
|
||||||
RichTextItem(title: "Card 3", subtitle: 'Aug 1, 2020 4:05 PM'),
|
RichTextItem(title: "Card 3", subtitle: 'Aug 1, 2020 4:05 PM'),
|
||||||
@ -34,11 +33,9 @@ class _MultiBoardListExampleState extends State<MultiBoardListExample> {
|
|||||||
RichTextItem(title: "Card 7", subtitle: 'Aug 1, 2020 4:05 PM'),
|
RichTextItem(title: "Card 7", subtitle: 'Aug 1, 2020 4:05 PM'),
|
||||||
RichTextItem(title: "Card 8", subtitle: 'Aug 1, 2020 4:05 PM'),
|
RichTextItem(title: "Card 8", subtitle: 'Aug 1, 2020 4:05 PM'),
|
||||||
TextItem("Card 9"),
|
TextItem("Card 9"),
|
||||||
];
|
]);
|
||||||
|
|
||||||
final column1 =
|
final group2 = AppFlowyGroupData(
|
||||||
AppFlowyBoardGroupData(id: "To Do", name: "To Do", items: a);
|
|
||||||
final column2 = AppFlowyBoardGroupData(
|
|
||||||
id: "In Progress",
|
id: "In Progress",
|
||||||
name: "In Progress",
|
name: "In Progress",
|
||||||
items: <AppFlowyGroupItem>[
|
items: <AppFlowyGroupItem>[
|
||||||
@ -47,12 +44,12 @@ class _MultiBoardListExampleState extends State<MultiBoardListExample> {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
final column3 = AppFlowyBoardGroupData(
|
final group3 = AppFlowyGroupData(
|
||||||
id: "Done", name: "Done", items: <AppFlowyGroupItem>[]);
|
id: "Done", name: "Done", items: <AppFlowyGroupItem>[]);
|
||||||
|
|
||||||
boardDataController.addGroup(column1);
|
controller.addGroup(group1);
|
||||||
boardDataController.addGroup(column2);
|
controller.addGroup(group2);
|
||||||
boardDataController.addGroup(column3);
|
controller.addGroup(group3);
|
||||||
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
@ -62,54 +59,45 @@ class _MultiBoardListExampleState extends State<MultiBoardListExample> {
|
|||||||
final config = AppFlowyBoardConfig(
|
final config = AppFlowyBoardConfig(
|
||||||
groupBackgroundColor: HexColor.fromHex('#F7F8FC'),
|
groupBackgroundColor: HexColor.fromHex('#F7F8FC'),
|
||||||
);
|
);
|
||||||
return Container(
|
return AppFlowyBoard(
|
||||||
color: Colors.white,
|
controller: controller,
|
||||||
child: Padding(
|
cardBuilder: (context, group, groupItem) {
|
||||||
padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 20),
|
return AppFlowyGroupCard(
|
||||||
child: AppFlowyBoard(
|
key: ValueKey(groupItem.id),
|
||||||
dataController: boardDataController,
|
child: _buildCard(groupItem),
|
||||||
footerBuilder: (context, columnData) {
|
);
|
||||||
return AppFlowyGroupFooter(
|
},
|
||||||
icon: const Icon(Icons.add, size: 20),
|
footerBuilder: (context, columnData) {
|
||||||
title: const Text('New'),
|
return AppFlowyGroupFooter(
|
||||||
height: 50,
|
icon: const Icon(Icons.add, size: 20),
|
||||||
margin: config.groupItemPadding,
|
title: const Text('New'),
|
||||||
);
|
height: 50,
|
||||||
},
|
margin: config.groupItemPadding,
|
||||||
headerBuilder: (context, columnData) {
|
);
|
||||||
return AppFlowyGroupHeader(
|
},
|
||||||
icon: const Icon(Icons.lightbulb_circle),
|
headerBuilder: (context, columnData) {
|
||||||
title: SizedBox(
|
return AppFlowyGroupHeader(
|
||||||
width: 60,
|
icon: const Icon(Icons.lightbulb_circle),
|
||||||
child: TextField(
|
title: SizedBox(
|
||||||
controller: TextEditingController()
|
width: 60,
|
||||||
..text = columnData.headerData.groupName,
|
child: TextField(
|
||||||
onSubmitted: (val) {
|
controller: TextEditingController()
|
||||||
boardDataController
|
..text = columnData.headerData.groupName,
|
||||||
.getGroupController(columnData.headerData.groupId)!
|
onSubmitted: (val) {
|
||||||
.updateGroupName(val);
|
controller
|
||||||
},
|
.getGroupController(columnData.headerData.groupId)!
|
||||||
),
|
.updateGroupName(val);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
addIcon: const Icon(Icons.add, size: 20),
|
),
|
||||||
moreIcon: const Icon(Icons.more_horiz, size: 20),
|
addIcon: const Icon(Icons.add, size: 20),
|
||||||
height: 50,
|
moreIcon: const Icon(Icons.more_horiz, size: 20),
|
||||||
margin: config.groupItemPadding,
|
height: 50,
|
||||||
);
|
margin: config.groupItemPadding,
|
||||||
},
|
);
|
||||||
cardBuilder: (context, column, columnItem) {
|
},
|
||||||
return AppFlowyGroupItemCard(
|
groupConstraints: const BoxConstraints.tightFor(width: 240),
|
||||||
key: ValueKey(columnItem.id),
|
config: config);
|
||||||
child: _buildCard(columnItem),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
groupConstraints: const BoxConstraints.tightFor(width: 240),
|
|
||||||
config: AppFlowyBoardConfig(
|
|
||||||
groupBackgroundColor: HexColor.fromHex('#F7F8FC'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildCard(AppFlowyGroupItem item) {
|
Widget _buildCard(AppFlowyGroupItem item) {
|
||||||
|
@ -9,11 +9,11 @@ class SingleBoardListExample extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _SingleBoardListExampleState extends State<SingleBoardListExample> {
|
class _SingleBoardListExampleState extends State<SingleBoardListExample> {
|
||||||
final AppFlowyBoardDataController boardData = AppFlowyBoardDataController();
|
final AppFlowyBoardController boardData = AppFlowyBoardController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
final column = AppFlowyBoardGroupData(
|
final column = AppFlowyGroupData(
|
||||||
id: "1",
|
id: "1",
|
||||||
name: "1",
|
name: "1",
|
||||||
items: [
|
items: [
|
||||||
@ -31,7 +31,7 @@ class _SingleBoardListExampleState extends State<SingleBoardListExample> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AppFlowyBoard(
|
return AppFlowyBoard(
|
||||||
dataController: boardData,
|
controller: boardData,
|
||||||
cardBuilder: (context, column, columnItem) {
|
cardBuilder: (context, column, columnItem) {
|
||||||
return _RowWidget(
|
return _RowWidget(
|
||||||
item: columnItem as TextItem, key: ObjectKey(columnItem));
|
item: columnItem as TextItem, key: ObjectKey(columnItem));
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
/// AppFlowyBoard library
|
||||||
library appflowy_board;
|
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/board_data.dart';
|
||||||
export 'src/widgets/styled_widgets/appflowy_styled_widgets.dart';
|
export 'src/widgets/styled_widgets/widgets.dart';
|
||||||
export 'src/widgets/board.dart';
|
export 'src/widgets/board.dart';
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
import 'package:appflowy_board/src/utils/log.dart';
|
import 'package:appflowy_board/src/utils/log.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.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_data.dart';
|
||||||
|
import 'board_group/group.dart';
|
||||||
|
import 'board_group/group_data.dart';
|
||||||
import 'reorder_flex/drag_state.dart';
|
import 'reorder_flex/drag_state.dart';
|
||||||
import 'reorder_flex/drag_target_interceptor.dart';
|
import 'reorder_flex/drag_target_interceptor.dart';
|
||||||
import 'reorder_flex/reorder_flex.dart';
|
import 'reorder_flex/reorder_flex.dart';
|
||||||
import 'reorder_phantom/phantom_controller.dart';
|
import 'reorder_phantom/phantom_controller.dart';
|
||||||
import '../rendering/board_overlay.dart';
|
import '../rendering/board_overlay.dart';
|
||||||
|
|
||||||
class AFBoardScrollManager {
|
class AppFlowyBoardScrollManager {
|
||||||
BoardGroupsState? _groupState;
|
AppFlowyBoardState? _groupState;
|
||||||
|
|
||||||
void scrollToBottom(String groupId, VoidCallback? completed) {
|
void scrollToBottom(String groupId, VoidCallback? completed) {
|
||||||
_groupState
|
_groupState
|
||||||
@ -48,26 +48,36 @@ class AppFlowyBoard extends StatelessWidget {
|
|||||||
final Widget? background;
|
final Widget? background;
|
||||||
|
|
||||||
/// The [cardBuilder] function which will be invoked on each card build.
|
/// 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].
|
/// the corresponding [AppFlowyGroupItem].
|
||||||
///
|
///
|
||||||
/// must return a widget.
|
/// must return a widget.
|
||||||
final AppFlowyBoardCardBuilder cardBuilder;
|
final AppFlowyBoardCardBuilder cardBuilder;
|
||||||
|
|
||||||
/// The [headerBuilder] function which will be invoked on each group build.
|
/// 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.
|
/// must return a widget.
|
||||||
final AppFlowyBoardHeaderBuilder? headerBuilder;
|
final AppFlowyBoardHeaderBuilder? headerBuilder;
|
||||||
|
|
||||||
/// The [footerBuilder] function which will be invoked on each group build.
|
/// 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.
|
/// must return a widget.
|
||||||
final AppFlowyBoardFooterBuilder? footerBuilder;
|
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;
|
final BoxConstraints groupConstraints;
|
||||||
|
|
||||||
@ -78,12 +88,12 @@ class AppFlowyBoard extends StatelessWidget {
|
|||||||
|
|
||||||
final AppFlowyBoardConfig config;
|
final AppFlowyBoardConfig config;
|
||||||
|
|
||||||
final AFBoardScrollManager? scrollManager;
|
final AppFlowyBoardScrollManager? scrollManager;
|
||||||
|
|
||||||
final BoardGroupsState _groupState = BoardGroupsState();
|
final AppFlowyBoardState _groupState = AppFlowyBoardState();
|
||||||
|
|
||||||
AppFlowyBoard({
|
AppFlowyBoard({
|
||||||
required this.dataController,
|
required this.controller,
|
||||||
required this.cardBuilder,
|
required this.cardBuilder,
|
||||||
this.background,
|
this.background,
|
||||||
this.footerBuilder,
|
this.footerBuilder,
|
||||||
@ -95,7 +105,7 @@ class AppFlowyBoard extends StatelessWidget {
|
|||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key) {
|
}) : super(key: key) {
|
||||||
phantomController = BoardPhantomController(
|
phantomController = BoardPhantomController(
|
||||||
delegate: dataController,
|
delegate: controller,
|
||||||
groupsState: _groupState,
|
groupsState: _groupState,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -103,16 +113,16 @@ class AppFlowyBoard extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ChangeNotifierProvider.value(
|
return ChangeNotifierProvider.value(
|
||||||
value: dataController,
|
value: controller,
|
||||||
child: Consumer<AppFlowyBoardDataController>(
|
child: Consumer<AppFlowyBoardController>(
|
||||||
builder: (context, notifier, child) {
|
builder: (context, notifier, child) {
|
||||||
if (scrollManager != null) {
|
if (scrollManager != null) {
|
||||||
scrollManager!._groupState = _groupState;
|
scrollManager!._groupState = _groupState;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _AppFlolwyBoardContent(
|
return _AppFlowyBoardContent(
|
||||||
config: config,
|
config: config,
|
||||||
dataController: dataController,
|
dataController: controller,
|
||||||
scrollController: scrollController,
|
scrollController: scrollController,
|
||||||
scrollManager: scrollManager,
|
scrollManager: scrollManager,
|
||||||
columnsState: _groupState,
|
columnsState: _groupState,
|
||||||
@ -123,7 +133,7 @@ class AppFlowyBoard extends StatelessWidget {
|
|||||||
footerBuilder: footerBuilder,
|
footerBuilder: footerBuilder,
|
||||||
headerBuilder: headerBuilder,
|
headerBuilder: headerBuilder,
|
||||||
phantomController: phantomController,
|
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 ScrollController? scrollController;
|
||||||
final OnDragStarted? onDragStarted;
|
final OnDragStarted? onDragStarted;
|
||||||
final OnReorder onReorder;
|
final OnReorder onReorder;
|
||||||
final OnDragEnded? onDragEnded;
|
final OnDragEnded? onDragEnded;
|
||||||
final AppFlowyBoardDataController dataController;
|
final AppFlowyBoardController dataController;
|
||||||
final Widget? background;
|
final Widget? background;
|
||||||
final AppFlowyBoardConfig config;
|
final AppFlowyBoardConfig config;
|
||||||
final ReorderFlexConfig reorderFlexConfig;
|
final ReorderFlexConfig reorderFlexConfig;
|
||||||
final BoxConstraints columnConstraints;
|
final BoxConstraints columnConstraints;
|
||||||
final AFBoardScrollManager? scrollManager;
|
final AppFlowyBoardScrollManager? scrollManager;
|
||||||
final BoardGroupsState columnsState;
|
final AppFlowyBoardState columnsState;
|
||||||
final AppFlowyBoardCardBuilder cardBuilder;
|
final AppFlowyBoardCardBuilder cardBuilder;
|
||||||
final AppFlowyBoardHeaderBuilder? headerBuilder;
|
final AppFlowyBoardHeaderBuilder? headerBuilder;
|
||||||
final AppFlowyBoardFooterBuilder? footerBuilder;
|
final AppFlowyBoardFooterBuilder? footerBuilder;
|
||||||
final OverlapDragTargetDelegate delegate;
|
final OverlapDragTargetDelegate delegate;
|
||||||
final BoardPhantomController phantomController;
|
final BoardPhantomController phantomController;
|
||||||
|
|
||||||
const _AppFlolwyBoardContent({
|
const _AppFlowyBoardContent({
|
||||||
required this.config,
|
required this.config,
|
||||||
required this.onReorder,
|
required this.onReorder,
|
||||||
required this.delegate,
|
required this.delegate,
|
||||||
@ -170,12 +180,12 @@ class _AppFlolwyBoardContent extends StatefulWidget {
|
|||||||
super(key: key);
|
super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<_AppFlolwyBoardContent> createState() => _AppFlowyBoardContentState();
|
State<_AppFlowyBoardContent> createState() => _AppFlowyBoardContentState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppFlowyBoardContentState extends State<_AppFlolwyBoardContent> {
|
class _AppFlowyBoardContentState extends State<_AppFlowyBoardContent> {
|
||||||
final GlobalKey _boardContentKey =
|
final GlobalKey _boardContentKey =
|
||||||
GlobalKey(debugLabel: '$_AppFlolwyBoardContent overlay key');
|
GlobalKey(debugLabel: '$_AppFlowyBoardContent overlay key');
|
||||||
late BoardOverlayEntry _overlayEntry;
|
late BoardOverlayEntry _overlayEntry;
|
||||||
|
|
||||||
final Map<String, GlobalObjectKey> _reorderFlexKeys = {};
|
final Map<String, GlobalObjectKey> _reorderFlexKeys = {};
|
||||||
@ -253,7 +263,7 @@ class _AppFlowyBoardContentState extends State<_AppFlolwyBoardContent> {
|
|||||||
return ChangeNotifierProvider.value(
|
return ChangeNotifierProvider.value(
|
||||||
key: ValueKey(columnData.id),
|
key: ValueKey(columnData.id),
|
||||||
value: widget.dataController.getGroupController(columnData.id),
|
value: widget.dataController.getGroupController(columnData.id),
|
||||||
child: Consumer<AFBoardGroupDataController>(
|
child: Consumer<AppFlowyGroupController>(
|
||||||
builder: (context, value, child) {
|
builder: (context, value, child) {
|
||||||
final boardColumn = AppFlowyBoardGroup(
|
final boardColumn = AppFlowyBoardGroup(
|
||||||
reorderFlexKey: reorderFlexKey,
|
reorderFlexKey: reorderFlexKey,
|
||||||
@ -289,12 +299,12 @@ class _AppFlowyBoardContentState extends State<_AppFlolwyBoardContent> {
|
|||||||
|
|
||||||
Widget? _buildHeader(
|
Widget? _buildHeader(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
AppFlowyBoardGroupData groupData,
|
AppFlowyGroupData groupData,
|
||||||
) {
|
) {
|
||||||
if (widget.headerBuilder == null) {
|
if (widget.headerBuilder == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return Selector<AFBoardGroupDataController, AppFlowyBoardGroupHeaderData>(
|
return Selector<AppFlowyGroupController, AppFlowyGroupHeaderData>(
|
||||||
selector: (context, controller) => controller.groupData.headerData,
|
selector: (context, controller) => controller.groupData.headerData,
|
||||||
builder: (context, headerData, _) {
|
builder: (context, headerData, _) {
|
||||||
return widget.headerBuilder!(context, groupData)!;
|
return widget.headerBuilder!(context, groupData)!;
|
||||||
@ -319,9 +329,9 @@ class _AppFlowyBoardContentState extends State<_AppFlolwyBoardContent> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _BoardGroupDataSourceImpl extends AppFlowyBoardGroupDataDataSource {
|
class _BoardGroupDataSourceImpl extends AppFlowyGroupDataDataSource {
|
||||||
String groupId;
|
String groupId;
|
||||||
final AppFlowyBoardDataController dataController;
|
final AppFlowyBoardController dataController;
|
||||||
|
|
||||||
_BoardGroupDataSourceImpl({
|
_BoardGroupDataSourceImpl({
|
||||||
required this.groupId,
|
required this.groupId,
|
||||||
@ -329,31 +339,34 @@ class _BoardGroupDataSourceImpl extends AppFlowyBoardGroupDataDataSource {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
AppFlowyBoardGroupData get groupData =>
|
AppFlowyGroupData get groupData =>
|
||||||
dataController.getGroupController(groupId)!.groupData;
|
dataController.getGroupController(groupId)!.groupData;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<String> get acceptedGroupIds => dataController.groupIds;
|
List<String> get acceptedGroupIds => dataController.groupIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
class BoardGroupContext {
|
/// A context contains the group states including the draggingState.
|
||||||
GlobalKey? groupKey;
|
///
|
||||||
|
/// [draggingState] represents the dragging state of the group.
|
||||||
|
class AppFlowyGroupContext {
|
||||||
DraggingState? draggingState;
|
DraggingState? draggingState;
|
||||||
}
|
}
|
||||||
|
|
||||||
class BoardGroupsState extends DraggingStateStorage
|
class AppFlowyBoardState extends DraggingStateStorage
|
||||||
with ReorderDragTargetIndexKeyStorage {
|
with ReorderDragTargetIndexKeyStorage {
|
||||||
/// Quick access to the [AppFlowyBoardGroup]
|
/// Quick access to the [AppFlowyBoardGroup], the [GlobalKey] is bind to the
|
||||||
final Map<String, GlobalKey> groupKeys = {};
|
/// AppFlowyBoardGroup's [ReorderFlex] widget.
|
||||||
|
final Map<String, GlobalKey> groupReorderFlexKeys = {};
|
||||||
final Map<String, DraggingState> groupDragStates = {};
|
final Map<String, DraggingState> groupDragStates = {};
|
||||||
final Map<String, Map<String, GlobalObjectKey>> groupDragDragTargets = {};
|
final Map<String, Map<String, GlobalObjectKey>> groupDragDragTargets = {};
|
||||||
|
|
||||||
void addGroup(String groupId, AppFlowyBoardGroup groupWidget) {
|
void addGroup(String groupId, AppFlowyBoardGroup groupWidget) {
|
||||||
groupKeys[groupId] = groupWidget.reorderFlexKey;
|
groupReorderFlexKeys[groupId] = groupWidget.reorderFlexKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReorderFlexState? getReorderFlexState({required String groupId}) {
|
ReorderFlexState? getReorderFlexState({required String groupId}) {
|
||||||
final flexGlobalKey = groupKeys[groupId];
|
final flexGlobalKey = groupReorderFlexKeys[groupId];
|
||||||
if (flexGlobalKey == null) return null;
|
if (flexGlobalKey == null) return null;
|
||||||
if (flexGlobalKey.currentState is! ReorderFlexState) return null;
|
if (flexGlobalKey.currentState is! ReorderFlexState) return null;
|
||||||
final state = flexGlobalKey.currentState as ReorderFlexState;
|
final state = flexGlobalKey.currentState as ReorderFlexState;
|
||||||
@ -361,7 +374,7 @@ class BoardGroupsState extends DraggingStateStorage
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReorderFlex? getReorderFlex({required String groupId}) {
|
ReorderFlex? getReorderFlex({required String groupId}) {
|
||||||
final flexGlobalKey = groupKeys[groupId];
|
final flexGlobalKey = groupReorderFlexKeys[groupId];
|
||||||
if (flexGlobalKey == null) return null;
|
if (flexGlobalKey == null) return null;
|
||||||
if (flexGlobalKey.currentWidget is! ReorderFlex) return null;
|
if (flexGlobalKey.currentWidget is! ReorderFlex) return null;
|
||||||
final widget = flexGlobalKey.currentWidget as ReorderFlex;
|
final widget = flexGlobalKey.currentWidget as ReorderFlex;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
|
import 'package:appflowy_board/src/widgets/board_group/group_data.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
import '../utils/log.dart';
|
import '../utils/log.dart';
|
||||||
import 'board_column/board_column_data.dart';
|
|
||||||
import 'reorder_flex/reorder_flex.dart';
|
import 'reorder_flex/reorder_flex.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'reorder_phantom/phantom_controller.dart';
|
import 'reorder_phantom/phantom_controller.dart';
|
||||||
@ -30,9 +30,9 @@ typedef OnMoveGroupItemToGroup = void Function(
|
|||||||
|
|
||||||
/// A controller for [AppFlowyBoard] widget.
|
/// A controller for [AppFlowyBoard] widget.
|
||||||
///
|
///
|
||||||
/// A [AppFlowyBoardDataController] can be used to provide an initial value of
|
/// A [AppFlowyBoardController] can be used to provide an initial value of
|
||||||
/// the board by calling [addGroup] method with the passed in parameter
|
/// the board by calling `addGroup` method with the passed in parameter
|
||||||
/// [AppFlowyBoardGroupData]. A [AppFlowyBoardGroupData] represents one
|
/// [AppFlowyGroupData]. A [AppFlowyGroupData] represents one
|
||||||
/// group data. Whenever the user modifies the board, this controller will
|
/// group data. Whenever the user modifies the board, this controller will
|
||||||
/// update the corresponding group data.
|
/// update the corresponding group data.
|
||||||
///
|
///
|
||||||
@ -44,9 +44,9 @@ typedef OnMoveGroupItemToGroup = void Function(
|
|||||||
///
|
///
|
||||||
/// [onMoveGroupItemToGroup] will get called when moving the group's item from
|
/// [onMoveGroupItemToGroup] will get called when moving the group's item from
|
||||||
/// one group to another group.
|
/// one group to another group.
|
||||||
class AppFlowyBoardDataController extends ChangeNotifier
|
class AppFlowyBoardController extends ChangeNotifier
|
||||||
with EquatableMixin, BoardPhantomControllerDelegate, ReoderFlexDataSource {
|
with EquatableMixin, BoardPhantomControllerDelegate, ReoderFlexDataSource {
|
||||||
final List<AppFlowyBoardGroupData> _groupDatas = [];
|
final List<AppFlowyGroupData> _groupDatas = [];
|
||||||
|
|
||||||
/// [onMoveGroup] will get called when moving the group from one position to
|
/// [onMoveGroup] will get called when moving the group from one position to
|
||||||
/// another.
|
/// another.
|
||||||
@ -59,18 +59,18 @@ class AppFlowyBoardDataController extends ChangeNotifier
|
|||||||
/// one group to another group.
|
/// one group to another group.
|
||||||
final OnMoveGroupItemToGroup? onMoveGroupItemToGroup;
|
final OnMoveGroupItemToGroup? onMoveGroupItemToGroup;
|
||||||
|
|
||||||
/// Returns the unmodifiable list of [AppFlowyBoardGroupData]
|
/// Returns the unmodifiable list of [AppFlowyGroupData]
|
||||||
UnmodifiableListView<AppFlowyBoardGroupData> get groupDatas =>
|
UnmodifiableListView<AppFlowyGroupData> get groupDatas =>
|
||||||
UnmodifiableListView(_groupDatas);
|
UnmodifiableListView(_groupDatas);
|
||||||
|
|
||||||
/// Returns list of group id
|
/// Returns list of group id
|
||||||
List<String> get groupIds =>
|
List<String> get groupIds =>
|
||||||
_groupDatas.map((groupData) => groupData.id).toList();
|
_groupDatas.map((groupData) => groupData.id).toList();
|
||||||
|
|
||||||
final LinkedHashMap<String, AFBoardGroupDataController> _groupControllers =
|
final LinkedHashMap<String, AppFlowyGroupController> _groupControllers =
|
||||||
LinkedHashMap();
|
LinkedHashMap();
|
||||||
|
|
||||||
AppFlowyBoardDataController({
|
AppFlowyBoardController({
|
||||||
this.onMoveGroup,
|
this.onMoveGroup,
|
||||||
this.onMoveGroupItem,
|
this.onMoveGroupItem,
|
||||||
this.onMoveGroupItemToGroup,
|
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
|
/// If you don't want to notify the listener after adding a new group, the
|
||||||
/// [notify] should set to false. Default value is true.
|
/// [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;
|
if (_groupControllers[groupData.id] != null) return;
|
||||||
|
|
||||||
final controller = AFBoardGroupDataController(groupData: groupData);
|
final controller = AppFlowyGroupController(groupData: groupData);
|
||||||
_groupDatas.add(groupData);
|
_groupDatas.add(groupData);
|
||||||
_groupControllers[groupData.id] = controller;
|
_groupControllers[groupData.id] = controller;
|
||||||
if (notify) notifyListeners();
|
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
|
/// If you don't want to notify the listener after adding the groups, the
|
||||||
/// [notify] should set to false. Default value is true.
|
/// [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) {
|
for (final column in groups) {
|
||||||
addGroup(column, notify: false);
|
addGroup(column, notify: false);
|
||||||
}
|
}
|
||||||
@ -133,6 +133,7 @@ class AppFlowyBoardDataController extends ChangeNotifier
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Remove all the groups controller.
|
/// Remove all the groups controller.
|
||||||
|
///
|
||||||
/// This method should get called when you want to remove all the current
|
/// This method should get called when you want to remove all the current
|
||||||
/// groups or get ready to reinitialize the [AppFlowyBoard].
|
/// groups or get ready to reinitialize the [AppFlowyBoard].
|
||||||
void clear() {
|
void clear() {
|
||||||
@ -141,8 +142,8 @@ class AppFlowyBoardDataController extends ChangeNotifier
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the [AFBoardGroupDataController] with id [groupId].
|
/// Returns the [AppFlowyGroupController] with id [groupId].
|
||||||
AFBoardGroupDataController? getGroupController(String groupId) {
|
AppFlowyGroupController? getGroupController(String groupId) {
|
||||||
final groupController = _groupControllers[groupId];
|
final groupController = _groupControllers[groupId];
|
||||||
if (groupController == null) {
|
if (groupController == null) {
|
||||||
Log.warn('Group:[$groupId] \'s controller is not exist');
|
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
|
/// Adds the [AppFlowyGroupItem] to the end of the group
|
||||||
|
///
|
||||||
/// If the group with id [groupId] is not exist, this method will do nothing.
|
/// If the group with id [groupId] is not exist, this method will do nothing.
|
||||||
void addGroupItem(String groupId, AppFlowyGroupItem item) {
|
void addGroupItem(String groupId, AppFlowyGroupItem item) {
|
||||||
getGroupController(groupId)?.add(item);
|
getGroupController(groupId)?.add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inserts the [AppFlowyGroupItem] at [index] in the group
|
/// Inserts the [AppFlowyGroupItem] at [index] in the group
|
||||||
|
///
|
||||||
/// It will do nothing if the group with id [groupId] is not exist
|
/// It will do nothing if the group with id [groupId] is not exist
|
||||||
void insertGroupItem(String groupId, int index, AppFlowyGroupItem item) {
|
void insertGroupItem(String groupId, int index, AppFlowyGroupItem item) {
|
||||||
getGroupController(groupId)?.insert(index, item);
|
getGroupController(groupId)?.insert(index, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes the item with id [itemId] from the group
|
/// Removes the item with id [itemId] from the group
|
||||||
|
///
|
||||||
/// It will do nothing if the group with id [groupId] is not exist
|
/// It will do nothing if the group with id [groupId] is not exist
|
||||||
void removeGroupItem(String groupId, String itemId) {
|
void removeGroupItem(String groupId, String itemId) {
|
||||||
getGroupController(groupId)?.removeWhere((item) => item.id == itemId);
|
getGroupController(groupId)?.removeWhere((item) => item.id == itemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces or inserts the [AppFlowyGroupItem] to the end of the group.
|
/// 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.
|
/// If the group with id [groupId] is not exist, this method will do nothing.
|
||||||
void updateGroupItem(String groupId, AppFlowyGroupItem item) {
|
void updateGroupItem(String groupId, AppFlowyGroupItem item) {
|
||||||
getGroupController(groupId)?.replaceOrInsertItem(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
|
@override
|
||||||
@protected
|
@protected
|
||||||
void moveGroupItemToAnotherGroup(
|
void moveGroupItemToAnotherGroup(
|
||||||
@ -228,12 +234,12 @@ class AppFlowyBoardDataController extends ChangeNotifier
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
AFBoardGroupDataController? controller(String groupId) {
|
AppFlowyGroupController? controller(String groupId) {
|
||||||
return _groupControllers[groupId];
|
return _groupControllers[groupId];
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get identifier => '$AppFlowyBoardDataController';
|
String get identifier => '$AppFlowyBoardController';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
UnmodifiableListView<ReoderFlexItem> get items =>
|
UnmodifiableListView<ReoderFlexItem> get items =>
|
||||||
@ -253,7 +259,7 @@ class AppFlowyBoardDataController extends ChangeNotifier
|
|||||||
groupController.removeAt(index);
|
groupController.removeAt(index);
|
||||||
|
|
||||||
Log.debug(
|
Log.debug(
|
||||||
'[$AppFlowyBoardDataController] Group:[$groupId] remove phantom, current count: ${groupController.items.length}');
|
'[$AppFlowyBoardController] Group:[$groupId] remove phantom, current count: ${groupController.items.length}');
|
||||||
}
|
}
|
||||||
return isExist;
|
return isExist;
|
||||||
}
|
}
|
||||||
|
@ -7,40 +7,40 @@ import '../../utils/log.dart';
|
|||||||
import '../reorder_phantom/phantom_controller.dart';
|
import '../reorder_phantom/phantom_controller.dart';
|
||||||
import '../reorder_flex/reorder_flex.dart';
|
import '../reorder_flex/reorder_flex.dart';
|
||||||
import '../reorder_flex/drag_target_interceptor.dart';
|
import '../reorder_flex/drag_target_interceptor.dart';
|
||||||
import 'board_column_data.dart';
|
import 'group_data.dart';
|
||||||
|
|
||||||
typedef OnGroupDragStarted = void Function(int index);
|
typedef OnGroupDragStarted = void Function(int index);
|
||||||
|
|
||||||
typedef OnGroupDragEnded = void Function(String listId);
|
typedef OnGroupDragEnded = void Function(String groupId);
|
||||||
|
|
||||||
typedef OnGroupReorder = void Function(
|
typedef OnGroupReorder = void Function(
|
||||||
String listId,
|
String groupId,
|
||||||
int fromIndex,
|
int fromIndex,
|
||||||
int toIndex,
|
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(
|
typedef AppFlowyBoardCardBuilder = Widget Function(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
AppFlowyBoardGroupData groupData,
|
AppFlowyGroupData groupData,
|
||||||
AppFlowyGroupItem item,
|
AppFlowyGroupItem item,
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef AppFlowyBoardHeaderBuilder = Widget? Function(
|
typedef AppFlowyBoardHeaderBuilder = Widget? Function(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
AppFlowyBoardGroupData groupData,
|
AppFlowyGroupData groupData,
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef AppFlowyBoardFooterBuilder = Widget Function(
|
typedef AppFlowyBoardFooterBuilder = Widget Function(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
AppFlowyBoardGroupData groupData,
|
AppFlowyGroupData groupData,
|
||||||
);
|
);
|
||||||
|
|
||||||
abstract class AppFlowyBoardGroupDataDataSource extends ReoderFlexDataSource {
|
abstract class AppFlowyGroupDataDataSource extends ReoderFlexDataSource {
|
||||||
AppFlowyBoardGroupData get groupData;
|
AppFlowyGroupData get groupData;
|
||||||
|
|
||||||
List<String> get acceptedGroupIds;
|
List<String> get acceptedGroupIds;
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ abstract class AppFlowyBoardGroupDataDataSource extends ReoderFlexDataSource {
|
|||||||
UnmodifiableListView<AppFlowyGroupItem> get items => groupData.items;
|
UnmodifiableListView<AppFlowyGroupItem> get items => groupData.items;
|
||||||
|
|
||||||
void debugPrint() {
|
void debugPrint() {
|
||||||
String msg = '[$AppFlowyBoardGroupDataDataSource] $groupData data: ';
|
String msg = '[$AppFlowyGroupDataDataSource] $groupData data: ';
|
||||||
for (var element in items) {
|
for (var element in items) {
|
||||||
msg = '$msg$element,';
|
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 {
|
class AppFlowyBoardGroup extends StatefulWidget {
|
||||||
final AppFlowyBoardGroupDataDataSource dataSource;
|
final AppFlowyGroupDataDataSource dataSource;
|
||||||
final ScrollController? scrollController;
|
final ScrollController? scrollController;
|
||||||
final ReorderFlexConfig config;
|
final ReorderFlexConfig config;
|
||||||
final OnGroupDragStarted? onDragStarted;
|
final OnGroupDragStarted? onDragStarted;
|
@ -1,10 +1,13 @@
|
|||||||
import 'dart:collection';
|
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:equatable/equatable.dart';
|
||||||
import 'package:flutter/material.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 {
|
abstract class AppFlowyGroupItem extends ReoderFlexItem {
|
||||||
bool get isPhantom => false;
|
bool get isPhantom => false;
|
||||||
|
|
||||||
@ -12,7 +15,8 @@ abstract class AppFlowyGroupItem extends ReoderFlexItem {
|
|||||||
String toString() => id;
|
String toString() => id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [AFBoardGroupDataController] is used to handle the [AppFlowyBoardGroupData].
|
/// [AppFlowyGroupController] is used to handle the [AppFlowyGroupData].
|
||||||
|
///
|
||||||
/// * Remove an item by calling [removeAt] method.
|
/// * Remove an item by calling [removeAt] method.
|
||||||
/// * Move item to another position by calling [move] method.
|
/// * Move item to another position by calling [move] method.
|
||||||
/// * Insert item to index by calling [insert] 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.
|
/// All there operations will notify listeners by default.
|
||||||
///
|
///
|
||||||
class AFBoardGroupDataController extends ChangeNotifier with EquatableMixin {
|
class AppFlowyGroupController extends ChangeNotifier with EquatableMixin {
|
||||||
final AppFlowyBoardGroupData groupData;
|
final AppFlowyGroupData groupData;
|
||||||
|
|
||||||
AFBoardGroupDataController({
|
AppFlowyGroupController({
|
||||||
required this.groupData,
|
required this.groupData,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -44,12 +48,12 @@ class AFBoardGroupDataController extends ChangeNotifier with EquatableMixin {
|
|||||||
/// Remove the item at [index].
|
/// Remove the item at [index].
|
||||||
/// * [index] the index of the item you want to remove
|
/// * [index] the index of the item you want to remove
|
||||||
/// * [notify] the default value of [notify] is true, it will notify the
|
/// * [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}) {
|
AppFlowyGroupItem removeAt(int index, {bool notify = true}) {
|
||||||
assert(index >= 0);
|
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);
|
final item = groupData._items.removeAt(index);
|
||||||
if (notify) {
|
if (notify) {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@ -74,7 +78,7 @@ class AFBoardGroupDataController extends ChangeNotifier with EquatableMixin {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Log.debug(
|
Log.debug(
|
||||||
'[$AFBoardGroupDataController] $groupData move item from $fromIndex to $toIndex');
|
'[$AppFlowyGroupController] $groupData move item from $fromIndex to $toIndex');
|
||||||
final item = groupData._items.removeAt(fromIndex);
|
final item = groupData._items.removeAt(fromIndex);
|
||||||
groupData._items.insert(toIndex, item);
|
groupData._items.insert(toIndex, item);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@ -87,8 +91,7 @@ class AFBoardGroupDataController extends ChangeNotifier with EquatableMixin {
|
|||||||
/// The default value of [notify] is true.
|
/// The default value of [notify] is true.
|
||||||
bool insert(int index, AppFlowyGroupItem item, {bool notify = true}) {
|
bool insert(int index, AppFlowyGroupItem item, {bool notify = true}) {
|
||||||
assert(index >= 0);
|
assert(index >= 0);
|
||||||
Log.debug(
|
Log.debug('[$AppFlowyGroupController] $groupData insert $item at $index');
|
||||||
'[$AFBoardGroupDataController] $groupData insert $item at $index');
|
|
||||||
|
|
||||||
if (_containsItem(item)) {
|
if (_containsItem(item)) {
|
||||||
return false;
|
return false;
|
||||||
@ -118,7 +121,7 @@ class AFBoardGroupDataController extends ChangeNotifier with EquatableMixin {
|
|||||||
void replace(int index, AppFlowyGroupItem newItem) {
|
void replace(int index, AppFlowyGroupItem newItem) {
|
||||||
if (groupData._items.isEmpty) {
|
if (groupData._items.isEmpty) {
|
||||||
groupData._items.add(newItem);
|
groupData._items.add(newItem);
|
||||||
Log.debug('[$AFBoardGroupDataController] $groupData add $newItem');
|
Log.debug('[$AppFlowyGroupController] $groupData add $newItem');
|
||||||
} else {
|
} else {
|
||||||
if (index >= groupData._items.length) {
|
if (index >= groupData._items.length) {
|
||||||
return;
|
return;
|
||||||
@ -127,7 +130,7 @@ class AFBoardGroupDataController extends ChangeNotifier with EquatableMixin {
|
|||||||
final removedItem = groupData._items.removeAt(index);
|
final removedItem = groupData._items.removeAt(index);
|
||||||
groupData._items.insert(index, newItem);
|
groupData._items.insert(index, newItem);
|
||||||
Log.debug(
|
Log.debug(
|
||||||
'[$AFBoardGroupDataController] $groupData replace $removedItem with $newItem at $index');
|
'[$AppFlowyGroupController] $groupData replace $removedItem with $newItem at $index');
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@ -151,22 +154,21 @@ class AFBoardGroupDataController extends ChangeNotifier with EquatableMixin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [AppFlowyBoardGroupData] represents the data of each group of the Board.
|
/// [AppFlowyGroupData] represents the data of each group of the Board.
|
||||||
class AppFlowyBoardGroupData<CustomData> extends ReoderFlexItem
|
class AppFlowyGroupData<CustomData> extends ReoderFlexItem with EquatableMixin {
|
||||||
with EquatableMixin {
|
|
||||||
@override
|
@override
|
||||||
final String id;
|
final String id;
|
||||||
AppFlowyBoardGroupHeaderData headerData;
|
AppFlowyGroupHeaderData headerData;
|
||||||
final List<AppFlowyGroupItem> _items;
|
final List<AppFlowyGroupItem> _items;
|
||||||
final CustomData? customData;
|
final CustomData? customData;
|
||||||
|
|
||||||
AppFlowyBoardGroupData({
|
AppFlowyGroupData({
|
||||||
this.customData,
|
this.customData,
|
||||||
required this.id,
|
required this.id,
|
||||||
required String name,
|
required String name,
|
||||||
List<AppFlowyGroupItem> items = const [],
|
List<AppFlowyGroupItem> items = const [],
|
||||||
}) : _items = items,
|
}) : _items = items,
|
||||||
headerData = AppFlowyBoardGroupHeaderData(
|
headerData = AppFlowyGroupHeaderData(
|
||||||
groupId: id,
|
groupId: id,
|
||||||
groupName: name,
|
groupName: name,
|
||||||
);
|
);
|
||||||
@ -184,10 +186,9 @@ class AppFlowyBoardGroupData<CustomData> extends ReoderFlexItem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppFlowyBoardGroupHeaderData {
|
class AppFlowyGroupHeaderData {
|
||||||
String groupId;
|
String groupId;
|
||||||
String groupName;
|
String groupName;
|
||||||
|
|
||||||
AppFlowyBoardGroupHeaderData(
|
AppFlowyGroupHeaderData({required this.groupId, required this.groupName});
|
||||||
{required this.groupId, required this.groupName});
|
|
||||||
}
|
}
|
@ -55,7 +55,7 @@ class OverlappingDragTargetInterceptor extends DragTargetInterceptor {
|
|||||||
final String reorderFlexId;
|
final String reorderFlexId;
|
||||||
final List<String> acceptedReorderFlexId;
|
final List<String> acceptedReorderFlexId;
|
||||||
final OverlapDragTargetDelegate delegate;
|
final OverlapDragTargetDelegate delegate;
|
||||||
final BoardGroupsState columnsState;
|
final AppFlowyBoardState columnsState;
|
||||||
Timer? _delayOperation;
|
Timer? _delayOperation;
|
||||||
|
|
||||||
OverlappingDragTargetInterceptor({
|
OverlappingDragTargetInterceptor({
|
||||||
|
@ -8,14 +8,14 @@ import '../reorder_flex/drag_target_interceptor.dart';
|
|||||||
import 'phantom_state.dart';
|
import 'phantom_state.dart';
|
||||||
|
|
||||||
abstract class BoardPhantomControllerDelegate {
|
abstract class BoardPhantomControllerDelegate {
|
||||||
AFBoardGroupDataController? controller(String groupId);
|
AppFlowyGroupController? controller(String groupId);
|
||||||
|
|
||||||
bool removePhantom(String groupId);
|
bool removePhantom(String groupId);
|
||||||
|
|
||||||
/// Insert the phantom into the group
|
/// Insert the phantom into the group
|
||||||
///
|
///
|
||||||
/// * [groupId] id of the group
|
/// * [groupId] id of the group
|
||||||
/// * [phantomIndex] the phantom occupies index
|
/// * [index] the phantom occupies index
|
||||||
void insertPhantom(
|
void insertPhantom(
|
||||||
String groupId,
|
String groupId,
|
||||||
int index,
|
int index,
|
||||||
@ -24,7 +24,7 @@ abstract class BoardPhantomControllerDelegate {
|
|||||||
|
|
||||||
/// Update the group's phantom index if it exists.
|
/// Update the group's phantom index if it exists.
|
||||||
/// [toGroupId] the id of the group
|
/// [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 updatePhantom(String groupId, int newIndex);
|
||||||
|
|
||||||
void moveGroupItemToAnotherGroup(
|
void moveGroupItemToAnotherGroup(
|
||||||
@ -39,7 +39,7 @@ class BoardPhantomController extends OverlapDragTargetDelegate
|
|||||||
with CrossReorderFlexDragTargetDelegate {
|
with CrossReorderFlexDragTargetDelegate {
|
||||||
PhantomRecord? phantomRecord;
|
PhantomRecord? phantomRecord;
|
||||||
final BoardPhantomControllerDelegate delegate;
|
final BoardPhantomControllerDelegate delegate;
|
||||||
final BoardGroupsState groupsState;
|
final AppFlowyBoardState groupsState;
|
||||||
final phantomState = GroupPhantomState();
|
final phantomState = GroupPhantomState();
|
||||||
BoardPhantomController({
|
BoardPhantomController({
|
||||||
required this.delegate,
|
required this.delegate,
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class AppFlowyGroupItemCard extends StatefulWidget {
|
class AppFlowyGroupCard extends StatefulWidget {
|
||||||
final Widget? child;
|
final Widget? child;
|
||||||
final EdgeInsets margin;
|
final EdgeInsets margin;
|
||||||
final BoxConstraints boxConstraints;
|
final BoxConstraints boxConstraints;
|
||||||
final BoxDecoration decoration;
|
final BoxDecoration decoration;
|
||||||
|
|
||||||
const AppFlowyGroupItemCard({
|
const AppFlowyGroupCard({
|
||||||
this.child,
|
this.child,
|
||||||
this.margin = const EdgeInsets.all(4),
|
this.margin = const EdgeInsets.all(4),
|
||||||
this.decoration = const BoxDecoration(
|
this.decoration = const BoxDecoration(
|
||||||
@ -18,10 +18,10 @@ class AppFlowyGroupItemCard extends StatefulWidget {
|
|||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<AppFlowyGroupItemCard> createState() => _AppFlowyGroupItemCardState();
|
State<AppFlowyGroupCard> createState() => _AppFlowyGroupCardState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppFlowyGroupItemCardState extends State<AppFlowyGroupItemCard> {
|
class _AppFlowyGroupCardState extends State<AppFlowyGroupCard> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
|
|
||||||
class SizeTransitionWithIntrinsicSize extends SingleChildRenderObjectWidget {
|
class SizeTransitionWithIntrinsicSize extends SingleChildRenderObjectWidget {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
name: appflowy_board
|
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
|
version: 0.0.6
|
||||||
homepage: https://github.com/AppFlowy-IO/AppFlowy
|
homepage: https://github.com/AppFlowy-IO/AppFlowy
|
||||||
repository: https://github.com/AppFlowy-IO/AppFlowy/tree/main/frontend/app_flowy/packages/appflowy_board
|
repository: https://github.com/AppFlowy-IO/AppFlowy/tree/main/frontend/app_flowy/packages/appflowy_board
|
||||||
|
Loading…
Reference in New Issue
Block a user