mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: update documentation
This commit is contained in:
parent
a3d2cef40a
commit
c7fdfb4090
@ -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 AFBoardDataController boardController;
|
late final AppFlowyBoardDataController boardController;
|
||||||
final MoveRowFFIService _rowService;
|
final MoveRowFFIService _rowService;
|
||||||
LinkedHashMap<String, GroupController> groupControllers = LinkedHashMap();
|
LinkedHashMap<String, GroupController> groupControllers = LinkedHashMap();
|
||||||
|
|
||||||
@ -34,8 +34,8 @@ 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 = AFBoardDataController(
|
boardController = AppFlowyBoardDataController(
|
||||||
onMoveColumn: (
|
onMoveGroup: (
|
||||||
fromColumnId,
|
fromColumnId,
|
||||||
fromIndex,
|
fromIndex,
|
||||||
toColumnId,
|
toColumnId,
|
||||||
@ -43,7 +43,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
) {
|
) {
|
||||||
_moveGroup(fromColumnId, toColumnId);
|
_moveGroup(fromColumnId, toColumnId);
|
||||||
},
|
},
|
||||||
onMoveColumnItem: (
|
onMoveGroupItem: (
|
||||||
columnId,
|
columnId,
|
||||||
fromIndex,
|
fromIndex,
|
||||||
toIndex,
|
toIndex,
|
||||||
@ -52,15 +52,15 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
final toRow = groupControllers[columnId]?.rowAtIndex(toIndex);
|
final toRow = groupControllers[columnId]?.rowAtIndex(toIndex);
|
||||||
_moveRow(fromRow, columnId, toRow);
|
_moveRow(fromRow, columnId, toRow);
|
||||||
},
|
},
|
||||||
onMoveColumnItemToColumn: (
|
onMoveGroupItemToGroup: (
|
||||||
fromColumnId,
|
fromGroupId,
|
||||||
fromIndex,
|
fromIndex,
|
||||||
toColumnId,
|
toGroupId,
|
||||||
toIndex,
|
toIndex,
|
||||||
) {
|
) {
|
||||||
final fromRow = groupControllers[fromColumnId]?.rowAtIndex(fromIndex);
|
final fromRow = groupControllers[fromGroupId]?.rowAtIndex(fromIndex);
|
||||||
final toRow = groupControllers[toColumnId]?.rowAtIndex(toIndex);
|
final toRow = groupControllers[toGroupId]?.rowAtIndex(toIndex);
|
||||||
_moveRow(fromRow, toColumnId, toRow);
|
_moveRow(fromRow, toGroupId, toRow);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -165,10 +165,10 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
boardController.clear();
|
boardController.clear();
|
||||||
|
|
||||||
//
|
//
|
||||||
List<AFBoardColumnData> columns = groups
|
List<AppFlowyBoardGroupData> columns = groups
|
||||||
.where((group) => fieldController.getField(group.fieldId) != null)
|
.where((group) => fieldController.getField(group.fieldId) != null)
|
||||||
.map((group) {
|
.map((group) {
|
||||||
return AFBoardColumnData(
|
return AppFlowyBoardGroupData(
|
||||||
id: group.groupId,
|
id: group.groupId,
|
||||||
name: group.desc,
|
name: group.desc,
|
||||||
items: _buildRows(group),
|
items: _buildRows(group),
|
||||||
@ -178,7 +178,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
boardController.addColumns(columns);
|
boardController.addGroups(columns);
|
||||||
|
|
||||||
for (final group in groups) {
|
for (final group in groups) {
|
||||||
final delegate = GroupControllerDelegateImpl(
|
final delegate = GroupControllerDelegateImpl(
|
||||||
@ -227,8 +227,8 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
if (isClosed) return;
|
if (isClosed) return;
|
||||||
for (final group in updatedGroups) {
|
for (final group in updatedGroups) {
|
||||||
final columnController =
|
final columnController =
|
||||||
boardController.getColumnController(group.groupId);
|
boardController.getGroupController(group.groupId);
|
||||||
columnController?.updateColumnName(group.desc);
|
columnController?.updateGroupName(group.desc);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onError: (err) {
|
onError: (err) {
|
||||||
@ -243,13 +243,13 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<AFColumnItem> _buildRows(GroupPB group) {
|
List<AppFlowyGroupItem> _buildRows(GroupPB group) {
|
||||||
final items = group.rows.map((row) {
|
final items = group.rows.map((row) {
|
||||||
final fieldContext = fieldController.getField(group.fieldId);
|
final fieldContext = fieldController.getField(group.fieldId);
|
||||||
return BoardColumnItem(row: row, fieldContext: fieldContext!);
|
return BoardColumnItem(row: row, fieldContext: fieldContext!);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
return <AFColumnItem>[...items];
|
return <AppFlowyGroupItem>[...items];
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadGrid(Emitter<BoardState> emit) async {
|
Future<void> _loadGrid(Emitter<BoardState> emit) async {
|
||||||
@ -335,7 +335,7 @@ class GridFieldEquatable extends Equatable {
|
|||||||
UnmodifiableListView<FieldPB> get value => UnmodifiableListView(_fields);
|
UnmodifiableListView<FieldPB> get value => UnmodifiableListView(_fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
class BoardColumnItem extends AFColumnItem {
|
class BoardColumnItem extends AppFlowyGroupItem {
|
||||||
final RowPB row;
|
final RowPB row;
|
||||||
final GridFieldContext fieldContext;
|
final GridFieldContext fieldContext;
|
||||||
|
|
||||||
@ -350,7 +350,7 @@ class BoardColumnItem extends AFColumnItem {
|
|||||||
|
|
||||||
class GroupControllerDelegateImpl extends GroupControllerDelegate {
|
class GroupControllerDelegateImpl extends GroupControllerDelegate {
|
||||||
final GridFieldController fieldController;
|
final GridFieldController fieldController;
|
||||||
final AFBoardDataController controller;
|
final AppFlowyBoardDataController controller;
|
||||||
final void Function(String, RowPB, int?) onNewColumnItem;
|
final void Function(String, RowPB, int?) onNewColumnItem;
|
||||||
|
|
||||||
GroupControllerDelegateImpl({
|
GroupControllerDelegateImpl({
|
||||||
@ -369,16 +369,16 @@ class GroupControllerDelegateImpl extends GroupControllerDelegate {
|
|||||||
|
|
||||||
if (index != null) {
|
if (index != null) {
|
||||||
final item = BoardColumnItem(row: row, fieldContext: fieldContext);
|
final item = BoardColumnItem(row: row, fieldContext: fieldContext);
|
||||||
controller.insertColumnItem(group.groupId, index, item);
|
controller.insertGroupItem(group.groupId, index, item);
|
||||||
} else {
|
} else {
|
||||||
final item = BoardColumnItem(row: row, fieldContext: fieldContext);
|
final item = BoardColumnItem(row: row, fieldContext: fieldContext);
|
||||||
controller.addColumnItem(group.groupId, item);
|
controller.addGroupItem(group.groupId, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void removeRow(GroupPB group, String rowId) {
|
void removeRow(GroupPB group, String rowId) {
|
||||||
controller.removeColumnItem(group.groupId, rowId);
|
controller.removeGroupItem(group.groupId, rowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -388,7 +388,7 @@ class GroupControllerDelegateImpl extends GroupControllerDelegate {
|
|||||||
Log.warn("FieldContext should not be null");
|
Log.warn("FieldContext should not be null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
controller.updateColumnItem(
|
controller.updateGroupItem(
|
||||||
group.groupId,
|
group.groupId,
|
||||||
BoardColumnItem(row: row, fieldContext: fieldContext),
|
BoardColumnItem(row: row, fieldContext: fieldContext),
|
||||||
);
|
);
|
||||||
@ -404,9 +404,9 @@ class GroupControllerDelegateImpl extends GroupControllerDelegate {
|
|||||||
final item = BoardColumnItem(row: row, fieldContext: fieldContext);
|
final item = BoardColumnItem(row: row, fieldContext: fieldContext);
|
||||||
|
|
||||||
if (index != null) {
|
if (index != null) {
|
||||||
controller.insertColumnItem(group.groupId, index, item);
|
controller.insertGroupItem(group.groupId, index, item);
|
||||||
} else {
|
} else {
|
||||||
controller.addColumnItem(group.groupId, item);
|
controller.addGroupItem(group.groupId, item);
|
||||||
}
|
}
|
||||||
onNewColumnItem(group.groupId, row, index);
|
onNewColumnItem(group.groupId, row, index);
|
||||||
}
|
}
|
||||||
|
@ -65,8 +65,8 @@ class _BoardContentState extends State<BoardContent> {
|
|||||||
late ScrollController scrollController;
|
late ScrollController scrollController;
|
||||||
late AFBoardScrollManager scrollManager;
|
late AFBoardScrollManager scrollManager;
|
||||||
|
|
||||||
final config = AFBoardConfig(
|
final config = AppFlowyBoardConfig(
|
||||||
columnBackgroundColor: HexColor.fromHex('#F7F8FC'),
|
groupBackgroundColor: HexColor.fromHex('#F7F8FC'),
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -101,7 +101,7 @@ class _BoardContentState extends State<BoardContent> {
|
|||||||
|
|
||||||
Expanded _buildBoard(BuildContext context) {
|
Expanded _buildBoard(BuildContext context) {
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: AFBoard(
|
child: AppFlowyBoard(
|
||||||
scrollManager: scrollManager,
|
scrollManager: scrollManager,
|
||||||
scrollController: scrollController,
|
scrollController: scrollController,
|
||||||
dataController: context.read<BoardBloc>().boardController,
|
dataController: context.read<BoardBloc>().boardController,
|
||||||
@ -112,9 +112,9 @@ class _BoardContentState extends State<BoardContent> {
|
|||||||
column,
|
column,
|
||||||
columnItem,
|
columnItem,
|
||||||
),
|
),
|
||||||
columnConstraints: const BoxConstraints.tightFor(width: 300),
|
groupConstraints: const BoxConstraints.tightFor(width: 300),
|
||||||
config: AFBoardConfig(
|
config: AppFlowyBoardConfig(
|
||||||
columnBackgroundColor: HexColor.fromHex('#F7F8FC'),
|
groupBackgroundColor: HexColor.fromHex('#F7F8FC'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -149,14 +149,14 @@ class _BoardContentState extends State<BoardContent> {
|
|||||||
|
|
||||||
Widget _buildHeader(
|
Widget _buildHeader(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
AFBoardColumnData columnData,
|
AppFlowyBoardGroupData columnData,
|
||||||
) {
|
) {
|
||||||
final boardCustomData = columnData.customData as BoardCustomData;
|
final boardCustomData = columnData.customData as BoardCustomData;
|
||||||
return AppFlowyColumnHeader(
|
return AppFlowyGroupHeader(
|
||||||
title: Flexible(
|
title: Flexible(
|
||||||
fit: FlexFit.tight,
|
fit: FlexFit.tight,
|
||||||
child: FlowyText.medium(
|
child: FlowyText.medium(
|
||||||
columnData.headerData.columnName,
|
columnData.headerData.groupName,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
overflow: TextOverflow.clip,
|
overflow: TextOverflow.clip,
|
||||||
color: context.read<AppTheme>().textColor,
|
color: context.read<AppTheme>().textColor,
|
||||||
@ -181,14 +181,14 @@ class _BoardContentState extends State<BoardContent> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildFooter(BuildContext context, AFBoardColumnData columnData) {
|
Widget _buildFooter(BuildContext context, AppFlowyBoardGroupData columnData) {
|
||||||
final boardCustomData = columnData.customData as BoardCustomData;
|
final boardCustomData = columnData.customData as BoardCustomData;
|
||||||
final group = boardCustomData.group;
|
final group = boardCustomData.group;
|
||||||
|
|
||||||
if (group.isDefault) {
|
if (group.isDefault) {
|
||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
} else {
|
} else {
|
||||||
return AppFlowyColumnFooter(
|
return AppFlowyGroupFooter(
|
||||||
icon: SizedBox(
|
icon: SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
width: 20,
|
width: 20,
|
||||||
@ -215,8 +215,8 @@ class _BoardContentState extends State<BoardContent> {
|
|||||||
|
|
||||||
Widget _buildCard(
|
Widget _buildCard(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
AFBoardColumnData column,
|
AppFlowyBoardGroupData column,
|
||||||
AFColumnItem columnItem,
|
AppFlowyGroupItem columnItem,
|
||||||
) {
|
) {
|
||||||
final boardColumnItem = columnItem as BoardColumnItem;
|
final boardColumnItem = columnItem as BoardColumnItem;
|
||||||
final rowPB = boardColumnItem.row;
|
final rowPB = boardColumnItem.row;
|
||||||
@ -242,7 +242,7 @@ class _BoardContentState extends State<BoardContent> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return AppFlowyColumnItemCard(
|
return AppFlowyGroupItemCard(
|
||||||
key: ValueKey(columnItem.id),
|
key: ValueKey(columnItem.id),
|
||||||
margin: config.cardPadding,
|
margin: config.cardPadding,
|
||||||
decoration: _makeBoxDecoration(context),
|
decoration: _makeBoxDecoration(context),
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
<a href="https://twitter.com/appflowy"><b>Twitter</b></a>
|
<a href="https://twitter.com/appflowy"><b>Twitter</b></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://github.com/AppFlowy-IO/AppFlowy/blob/main/frontend/app_flowy/packages/appflowy_board/example/gifs/appflowy_board_video_1.gif?raw=true" width="680" title="AppFlowyBoard">
|
<img src="https://github.com/AppFlowy-IO/AppFlowy/blob/main/frontend/app_flowy/packages/appflowy_board/example/gifs/appflowy_board_video_1.gif?raw=true" width="680" title="AppFlowyBoard">
|
||||||
</p>
|
</p>
|
||||||
@ -30,6 +31,7 @@ Add the AppFlowy Board [Flutter package](https://docs.flutter.dev/development/pa
|
|||||||
With Flutter:
|
With Flutter:
|
||||||
```dart
|
```dart
|
||||||
flutter pub add appflowy_board
|
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 (and run an implicit flutter pub get):
|
||||||
@ -38,6 +40,8 @@ dependencies:
|
|||||||
appflowy_board: ^0.0.6
|
appflowy_board: ^0.0.6
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Create board
|
||||||
|
|
||||||
Import the package in your Dart file:
|
Import the package in your Dart file:
|
||||||
```dart
|
```dart
|
||||||
import 'package:appflowy_board/appflowy_board.dart';
|
import 'package:appflowy_board/appflowy_board.dart';
|
||||||
@ -47,14 +51,18 @@ import 'package:appflowy_board/appflowy_board.dart';
|
|||||||
To quickly grasp how it can be used, look at the /example/lib folder.
|
To quickly grasp how it can be used, look at the /example/lib folder.
|
||||||
First, run main.dart to play with the demo.
|
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 AFBoard() object.
|
||||||
* In the AFBoard() object, you can find:
|
* 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.
|
* 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.
|
* 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="100%" 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.
|
||||||
@ -68,4 +76,4 @@ Please look at [CONTRIBUTING.md](https://appflowy.gitbook.io/docs/essential-docu
|
|||||||
Distributed under the AGPLv3 License. See [LICENSE](https://github.com/AppFlowy-IO/AppFlowy-Docs/blob/main/LICENSE) for more information.
|
Distributed under the AGPLv3 License. See [LICENSE](https://github.com/AppFlowy-IO/AppFlowy-Docs/blob/main/LICENSE) for more information.
|
||||||
|
|
||||||
|
|
||||||
|
d
|
@ -9,21 +9,22 @@ class MultiBoardListExample extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _MultiBoardListExampleState extends State<MultiBoardListExample> {
|
class _MultiBoardListExampleState extends State<MultiBoardListExample> {
|
||||||
final AFBoardDataController boardDataController = AFBoardDataController(
|
final AppFlowyBoardDataController boardDataController =
|
||||||
onMoveColumn: (fromColumnId, fromIndex, toColumnId, toIndex) {
|
AppFlowyBoardDataController(
|
||||||
|
onMoveGroup: (fromColumnId, fromIndex, toColumnId, toIndex) {
|
||||||
// debugPrint('Move column from $fromIndex to $toIndex');
|
// debugPrint('Move column from $fromIndex to $toIndex');
|
||||||
},
|
},
|
||||||
onMoveColumnItem: (columnId, fromIndex, toIndex) {
|
onMoveGroupItem: (columnId, fromIndex, toIndex) {
|
||||||
// debugPrint('Move $columnId:$fromIndex to $columnId:$toIndex');
|
// debugPrint('Move $columnId:$fromIndex to $columnId:$toIndex');
|
||||||
},
|
},
|
||||||
onMoveColumnItemToColumn: (fromColumnId, fromIndex, toColumnId, toIndex) {
|
onMoveGroupItemToGroup: (fromColumnId, fromIndex, toColumnId, toIndex) {
|
||||||
// debugPrint('Move $fromColumnId:$fromIndex to $toColumnId:$toIndex');
|
// debugPrint('Move $fromColumnId:$fromIndex to $toColumnId:$toIndex');
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
List<AFColumnItem> a = [
|
List<AppFlowyGroupItem> a = [
|
||||||
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'),
|
||||||
@ -35,82 +36,83 @@ class _MultiBoardListExampleState extends State<MultiBoardListExample> {
|
|||||||
TextItem("Card 9"),
|
TextItem("Card 9"),
|
||||||
];
|
];
|
||||||
|
|
||||||
final column1 = AFBoardColumnData(id: "To Do", name: "To Do", items: a);
|
final column1 =
|
||||||
final column2 = AFBoardColumnData(
|
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: <AFColumnItem>[
|
items: <AppFlowyGroupItem>[
|
||||||
RichTextItem(title: "Card 10", subtitle: 'Aug 1, 2020 4:05 PM'),
|
RichTextItem(title: "Card 10", subtitle: 'Aug 1, 2020 4:05 PM'),
|
||||||
TextItem("Card 11"),
|
TextItem("Card 11"),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
final column3 =
|
final column3 = AppFlowyBoardGroupData(
|
||||||
AFBoardColumnData(id: "Done", name: "Done", items: <AFColumnItem>[]);
|
id: "Done", name: "Done", items: <AppFlowyGroupItem>[]);
|
||||||
|
|
||||||
boardDataController.addColumn(column1);
|
boardDataController.addGroup(column1);
|
||||||
boardDataController.addColumn(column2);
|
boardDataController.addGroup(column2);
|
||||||
boardDataController.addColumn(column3);
|
boardDataController.addGroup(column3);
|
||||||
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final config = AFBoardConfig(
|
final config = AppFlowyBoardConfig(
|
||||||
columnBackgroundColor: HexColor.fromHex('#F7F8FC'),
|
groupBackgroundColor: HexColor.fromHex('#F7F8FC'),
|
||||||
);
|
);
|
||||||
return Container(
|
return Container(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 20),
|
padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 20),
|
||||||
child: AFBoard(
|
child: AppFlowyBoard(
|
||||||
dataController: boardDataController,
|
dataController: boardDataController,
|
||||||
footerBuilder: (context, columnData) {
|
footerBuilder: (context, columnData) {
|
||||||
return AppFlowyColumnFooter(
|
return AppFlowyGroupFooter(
|
||||||
icon: const Icon(Icons.add, size: 20),
|
icon: const Icon(Icons.add, size: 20),
|
||||||
title: const Text('New'),
|
title: const Text('New'),
|
||||||
height: 50,
|
height: 50,
|
||||||
margin: config.columnItemPadding,
|
margin: config.groupItemPadding,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
headerBuilder: (context, columnData) {
|
headerBuilder: (context, columnData) {
|
||||||
return AppFlowyColumnHeader(
|
return AppFlowyGroupHeader(
|
||||||
icon: const Icon(Icons.lightbulb_circle),
|
icon: const Icon(Icons.lightbulb_circle),
|
||||||
title: SizedBox(
|
title: SizedBox(
|
||||||
width: 60,
|
width: 60,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: TextEditingController()
|
controller: TextEditingController()
|
||||||
..text = columnData.headerData.columnName,
|
..text = columnData.headerData.groupName,
|
||||||
onSubmitted: (val) {
|
onSubmitted: (val) {
|
||||||
boardDataController
|
boardDataController
|
||||||
.getColumnController(columnData.headerData.columnId)!
|
.getGroupController(columnData.headerData.groupId)!
|
||||||
.updateColumnName(val);
|
.updateGroupName(val);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
addIcon: const Icon(Icons.add, size: 20),
|
addIcon: const Icon(Icons.add, size: 20),
|
||||||
moreIcon: const Icon(Icons.more_horiz, size: 20),
|
moreIcon: const Icon(Icons.more_horiz, size: 20),
|
||||||
height: 50,
|
height: 50,
|
||||||
margin: config.columnItemPadding,
|
margin: config.groupItemPadding,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
cardBuilder: (context, column, columnItem) {
|
cardBuilder: (context, column, columnItem) {
|
||||||
return AppFlowyColumnItemCard(
|
return AppFlowyGroupItemCard(
|
||||||
key: ValueKey(columnItem.id),
|
key: ValueKey(columnItem.id),
|
||||||
child: _buildCard(columnItem),
|
child: _buildCard(columnItem),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
columnConstraints: const BoxConstraints.tightFor(width: 240),
|
groupConstraints: const BoxConstraints.tightFor(width: 240),
|
||||||
config: AFBoardConfig(
|
config: AppFlowyBoardConfig(
|
||||||
columnBackgroundColor: HexColor.fromHex('#F7F8FC'),
|
groupBackgroundColor: HexColor.fromHex('#F7F8FC'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildCard(AFColumnItem item) {
|
Widget _buildCard(AppFlowyGroupItem item) {
|
||||||
if (item is TextItem) {
|
if (item is TextItem) {
|
||||||
return Align(
|
return Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
@ -172,7 +174,7 @@ class _RichTextCardState extends State<RichTextCard> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TextItem extends AFColumnItem {
|
class TextItem extends AppFlowyGroupItem {
|
||||||
final String s;
|
final String s;
|
||||||
|
|
||||||
TextItem(this.s);
|
TextItem(this.s);
|
||||||
@ -181,7 +183,7 @@ class TextItem extends AFColumnItem {
|
|||||||
String get id => s;
|
String get id => s;
|
||||||
}
|
}
|
||||||
|
|
||||||
class RichTextItem extends AFColumnItem {
|
class RichTextItem extends AppFlowyGroupItem {
|
||||||
final String title;
|
final String title;
|
||||||
final String subtitle;
|
final String subtitle;
|
||||||
|
|
||||||
|
@ -9,11 +9,11 @@ class SingleBoardListExample extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _SingleBoardListExampleState extends State<SingleBoardListExample> {
|
class _SingleBoardListExampleState extends State<SingleBoardListExample> {
|
||||||
final AFBoardDataController boardData = AFBoardDataController();
|
final AppFlowyBoardDataController boardData = AppFlowyBoardDataController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
final column = AFBoardColumnData(
|
final column = AppFlowyBoardGroupData(
|
||||||
id: "1",
|
id: "1",
|
||||||
name: "1",
|
name: "1",
|
||||||
items: [
|
items: [
|
||||||
@ -24,13 +24,13 @@ class _SingleBoardListExampleState extends State<SingleBoardListExample> {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
boardData.addColumn(column);
|
boardData.addGroup(column);
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AFBoard(
|
return AppFlowyBoard(
|
||||||
dataController: boardData,
|
dataController: boardData,
|
||||||
cardBuilder: (context, column, columnItem) {
|
cardBuilder: (context, column, columnItem) {
|
||||||
return _RowWidget(
|
return _RowWidget(
|
||||||
@ -55,7 +55,7 @@ class _RowWidget extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TextItem extends AFColumnItem {
|
class TextItem extends AppFlowyGroupItem {
|
||||||
final String s;
|
final String s;
|
||||||
|
|
||||||
TextItem(this.s);
|
TextItem(this.s);
|
||||||
|
@ -11,70 +11,78 @@ import 'reorder_phantom/phantom_controller.dart';
|
|||||||
import '../rendering/board_overlay.dart';
|
import '../rendering/board_overlay.dart';
|
||||||
|
|
||||||
class AFBoardScrollManager {
|
class AFBoardScrollManager {
|
||||||
BoardColumnsState? _columnState;
|
BoardGroupsState? _groupState;
|
||||||
|
|
||||||
// AFBoardScrollManager();
|
void scrollToBottom(String groupId, VoidCallback? completed) {
|
||||||
|
_groupState
|
||||||
void scrollToBottom(String columnId, VoidCallback? completed) {
|
?.getReorderFlexState(groupId: groupId)
|
||||||
_columnState
|
|
||||||
?.getReorderFlexState(columnId: columnId)
|
|
||||||
?.scrollToBottom(completed);
|
?.scrollToBottom(completed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AFBoardConfig {
|
class AppFlowyBoardConfig {
|
||||||
final double cornerRadius;
|
final double cornerRadius;
|
||||||
final EdgeInsets columnPadding;
|
final EdgeInsets groupPadding;
|
||||||
final EdgeInsets columnItemPadding;
|
final EdgeInsets groupItemPadding;
|
||||||
final EdgeInsets footerPadding;
|
final EdgeInsets footerPadding;
|
||||||
final EdgeInsets headerPadding;
|
final EdgeInsets headerPadding;
|
||||||
final EdgeInsets cardPadding;
|
final EdgeInsets cardPadding;
|
||||||
final Color columnBackgroundColor;
|
final Color groupBackgroundColor;
|
||||||
|
|
||||||
const AFBoardConfig({
|
const AppFlowyBoardConfig({
|
||||||
this.cornerRadius = 6.0,
|
this.cornerRadius = 6.0,
|
||||||
this.columnPadding = const EdgeInsets.symmetric(horizontal: 8),
|
this.groupPadding = const EdgeInsets.symmetric(horizontal: 8),
|
||||||
this.columnItemPadding = const EdgeInsets.symmetric(horizontal: 12),
|
this.groupItemPadding = const EdgeInsets.symmetric(horizontal: 12),
|
||||||
this.footerPadding = const EdgeInsets.symmetric(horizontal: 12),
|
this.footerPadding = const EdgeInsets.symmetric(horizontal: 12),
|
||||||
this.headerPadding = const EdgeInsets.symmetric(horizontal: 16),
|
this.headerPadding = const EdgeInsets.symmetric(horizontal: 16),
|
||||||
this.cardPadding = const EdgeInsets.symmetric(horizontal: 3, vertical: 4),
|
this.cardPadding = const EdgeInsets.symmetric(horizontal: 3, vertical: 4),
|
||||||
this.columnBackgroundColor = Colors.transparent,
|
this.groupBackgroundColor = Colors.transparent,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class AFBoard extends StatelessWidget {
|
class AppFlowyBoard extends StatelessWidget {
|
||||||
/// The direction to use as the main axis.
|
/// The direction to use as the main axis.
|
||||||
final Axis direction = Axis.vertical;
|
final Axis direction = Axis.vertical;
|
||||||
|
|
||||||
///
|
/// The widget that will be rendered as the background of the board.
|
||||||
final Widget? background;
|
final Widget? background;
|
||||||
|
|
||||||
|
/// The [cardBuilder] function which will be invoked on each card build.
|
||||||
|
/// The [cardBuilder] takes the [BuildContext],[AppFlowyBoardGroupData] and
|
||||||
|
/// the corresponding [AppFlowyGroupItem].
|
||||||
///
|
///
|
||||||
final AFBoardColumnCardBuilder cardBuilder;
|
/// must return a widget.
|
||||||
|
final AppFlowyBoardCardBuilder cardBuilder;
|
||||||
|
|
||||||
|
/// The [headerBuilder] function which will be invoked on each group build.
|
||||||
|
/// The [headerBuilder] takes the [BuildContext] and [AppFlowyBoardGroupData].
|
||||||
|
///
|
||||||
|
/// must return a widget.
|
||||||
|
final AppFlowyBoardHeaderBuilder? headerBuilder;
|
||||||
|
|
||||||
|
/// The [footerBuilder] function which will be invoked on each group build.
|
||||||
|
/// The [footerBuilder] takes the [BuildContext] and [AppFlowyBoardGroupData].
|
||||||
|
///
|
||||||
|
/// must return a widget.
|
||||||
|
final AppFlowyBoardFooterBuilder? footerBuilder;
|
||||||
|
|
||||||
///
|
///
|
||||||
final AFBoardColumnHeaderBuilder? headerBuilder;
|
final AppFlowyBoardDataController dataController;
|
||||||
|
|
||||||
///
|
final BoxConstraints groupConstraints;
|
||||||
final AFBoardColumnFooterBuilder? footerBuilder;
|
|
||||||
|
|
||||||
///
|
|
||||||
final AFBoardDataController dataController;
|
|
||||||
|
|
||||||
final BoxConstraints columnConstraints;
|
|
||||||
|
|
||||||
///
|
///
|
||||||
late final BoardPhantomController phantomController;
|
late final BoardPhantomController phantomController;
|
||||||
|
|
||||||
final ScrollController? scrollController;
|
final ScrollController? scrollController;
|
||||||
|
|
||||||
final AFBoardConfig config;
|
final AppFlowyBoardConfig config;
|
||||||
|
|
||||||
final AFBoardScrollManager? scrollManager;
|
final AFBoardScrollManager? scrollManager;
|
||||||
|
|
||||||
final BoardColumnsState _columnState = BoardColumnsState();
|
final BoardGroupsState _groupState = BoardGroupsState();
|
||||||
|
|
||||||
AFBoard({
|
AppFlowyBoard({
|
||||||
required this.dataController,
|
required this.dataController,
|
||||||
required this.cardBuilder,
|
required this.cardBuilder,
|
||||||
this.background,
|
this.background,
|
||||||
@ -82,13 +90,13 @@ class AFBoard extends StatelessWidget {
|
|||||||
this.headerBuilder,
|
this.headerBuilder,
|
||||||
this.scrollController,
|
this.scrollController,
|
||||||
this.scrollManager,
|
this.scrollManager,
|
||||||
this.columnConstraints = const BoxConstraints(maxWidth: 200),
|
this.groupConstraints = const BoxConstraints(maxWidth: 200),
|
||||||
this.config = const AFBoardConfig(),
|
this.config = const AppFlowyBoardConfig(),
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key) {
|
}) : super(key: key) {
|
||||||
phantomController = BoardPhantomController(
|
phantomController = BoardPhantomController(
|
||||||
delegate: dataController,
|
delegate: dataController,
|
||||||
columnsState: _columnState,
|
groupsState: _groupState,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,10 +104,10 @@ class AFBoard extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ChangeNotifierProvider.value(
|
return ChangeNotifierProvider.value(
|
||||||
value: dataController,
|
value: dataController,
|
||||||
child: Consumer<AFBoardDataController>(
|
child: Consumer<AppFlowyBoardDataController>(
|
||||||
builder: (context, notifier, child) {
|
builder: (context, notifier, child) {
|
||||||
if (scrollManager != null) {
|
if (scrollManager != null) {
|
||||||
scrollManager!._columnState = _columnState;
|
scrollManager!._groupState = _groupState;
|
||||||
}
|
}
|
||||||
|
|
||||||
return AFBoardContent(
|
return AFBoardContent(
|
||||||
@ -107,15 +115,15 @@ class AFBoard extends StatelessWidget {
|
|||||||
dataController: dataController,
|
dataController: dataController,
|
||||||
scrollController: scrollController,
|
scrollController: scrollController,
|
||||||
scrollManager: scrollManager,
|
scrollManager: scrollManager,
|
||||||
columnsState: _columnState,
|
columnsState: _groupState,
|
||||||
background: background,
|
background: background,
|
||||||
delegate: phantomController,
|
delegate: phantomController,
|
||||||
columnConstraints: columnConstraints,
|
columnConstraints: groupConstraints,
|
||||||
cardBuilder: cardBuilder,
|
cardBuilder: cardBuilder,
|
||||||
footBuilder: footerBuilder,
|
footerBuilder: footerBuilder,
|
||||||
headerBuilder: headerBuilder,
|
headerBuilder: headerBuilder,
|
||||||
phantomController: phantomController,
|
phantomController: phantomController,
|
||||||
onReorder: dataController.moveColumn,
|
onReorder: dataController.moveGroup,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -128,22 +136,22 @@ class AFBoardContent extends StatefulWidget {
|
|||||||
final OnDragStarted? onDragStarted;
|
final OnDragStarted? onDragStarted;
|
||||||
final OnReorder onReorder;
|
final OnReorder onReorder;
|
||||||
final OnDragEnded? onDragEnded;
|
final OnDragEnded? onDragEnded;
|
||||||
final AFBoardDataController dataController;
|
final AppFlowyBoardDataController dataController;
|
||||||
final Widget? background;
|
final Widget? background;
|
||||||
final AFBoardConfig config;
|
final AppFlowyBoardConfig config;
|
||||||
final ReorderFlexConfig reorderFlexConfig;
|
final ReorderFlexConfig reorderFlexConfig;
|
||||||
final BoxConstraints columnConstraints;
|
final BoxConstraints columnConstraints;
|
||||||
final AFBoardScrollManager? scrollManager;
|
final AFBoardScrollManager? scrollManager;
|
||||||
final BoardColumnsState columnsState;
|
final BoardGroupsState columnsState;
|
||||||
|
|
||||||
///
|
///
|
||||||
final AFBoardColumnCardBuilder cardBuilder;
|
final AppFlowyBoardCardBuilder cardBuilder;
|
||||||
|
|
||||||
///
|
///
|
||||||
final AFBoardColumnHeaderBuilder? headerBuilder;
|
final AppFlowyBoardHeaderBuilder? headerBuilder;
|
||||||
|
|
||||||
///
|
///
|
||||||
final AFBoardColumnFooterBuilder? footBuilder;
|
final AppFlowyBoardFooterBuilder? footerBuilder;
|
||||||
|
|
||||||
final OverlapDragTargetDelegate delegate;
|
final OverlapDragTargetDelegate delegate;
|
||||||
|
|
||||||
@ -162,7 +170,7 @@ class AFBoardContent extends StatefulWidget {
|
|||||||
this.background,
|
this.background,
|
||||||
required this.columnConstraints,
|
required this.columnConstraints,
|
||||||
required this.cardBuilder,
|
required this.cardBuilder,
|
||||||
this.footBuilder,
|
this.footerBuilder,
|
||||||
this.headerBuilder,
|
this.headerBuilder,
|
||||||
required this.phantomController,
|
required this.phantomController,
|
||||||
Key? key,
|
Key? key,
|
||||||
@ -178,13 +186,15 @@ class _AFBoardContentState extends State<AFBoardContent> {
|
|||||||
GlobalKey(debugLabel: '$AFBoardContent overlay key');
|
GlobalKey(debugLabel: '$AFBoardContent overlay key');
|
||||||
late BoardOverlayEntry _overlayEntry;
|
late BoardOverlayEntry _overlayEntry;
|
||||||
|
|
||||||
|
final Map<String, GlobalObjectKey> _reorderFlexKeys = {};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_overlayEntry = BoardOverlayEntry(
|
_overlayEntry = BoardOverlayEntry(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
final interceptor = OverlappingDragTargetInterceptor(
|
final interceptor = OverlappingDragTargetInterceptor(
|
||||||
reorderFlexId: widget.dataController.identifier,
|
reorderFlexId: widget.dataController.identifier,
|
||||||
acceptedReorderFlexId: widget.dataController.columnIds,
|
acceptedReorderFlexId: widget.dataController.groupIds,
|
||||||
delegate: widget.delegate,
|
delegate: widget.delegate,
|
||||||
columnsState: widget.columnsState,
|
columnsState: widget.columnsState,
|
||||||
);
|
);
|
||||||
@ -233,40 +243,45 @@ class _AFBoardContentState extends State<AFBoardContent> {
|
|||||||
|
|
||||||
List<Widget> _buildColumns() {
|
List<Widget> _buildColumns() {
|
||||||
final List<Widget> children =
|
final List<Widget> children =
|
||||||
widget.dataController.columnDatas.asMap().entries.map(
|
widget.dataController.groupDatas.asMap().entries.map(
|
||||||
(item) {
|
(item) {
|
||||||
final columnData = item.value;
|
final columnData = item.value;
|
||||||
final columnIndex = item.key;
|
final columnIndex = item.key;
|
||||||
|
|
||||||
final dataSource = _BoardColumnDataSourceImpl(
|
final dataSource = _BoardGroupDataSourceImpl(
|
||||||
columnId: columnData.id,
|
groupId: columnData.id,
|
||||||
dataController: widget.dataController,
|
dataController: widget.dataController,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (_reorderFlexKeys[columnData.id] == null) {
|
||||||
|
_reorderFlexKeys[columnData.id] = GlobalObjectKey(columnData.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalObjectKey reorderFlexKey = _reorderFlexKeys[columnData.id]!;
|
||||||
return ChangeNotifierProvider.value(
|
return ChangeNotifierProvider.value(
|
||||||
key: ValueKey(columnData.id),
|
key: ValueKey(columnData.id),
|
||||||
value: widget.dataController.getColumnController(columnData.id),
|
value: widget.dataController.getGroupController(columnData.id),
|
||||||
child: Consumer<AFBoardColumnDataController>(
|
child: Consumer<AFBoardGroupDataController>(
|
||||||
builder: (context, value, child) {
|
builder: (context, value, child) {
|
||||||
final boardColumn = AFBoardColumnWidget(
|
final boardColumn = AppFlowyBoardGroupWidget(
|
||||||
|
reorderFlexKey: reorderFlexKey,
|
||||||
// key: PageStorageKey<String>(columnData.id),
|
// key: PageStorageKey<String>(columnData.id),
|
||||||
margin: _marginFromIndex(columnIndex),
|
margin: _marginFromIndex(columnIndex),
|
||||||
itemMargin: widget.config.columnItemPadding,
|
itemMargin: widget.config.groupItemPadding,
|
||||||
headerBuilder: _buildHeader,
|
headerBuilder: _buildHeader,
|
||||||
footBuilder: widget.footBuilder,
|
footerBuilder: widget.footerBuilder,
|
||||||
cardBuilder: widget.cardBuilder,
|
cardBuilder: widget.cardBuilder,
|
||||||
dataSource: dataSource,
|
dataSource: dataSource,
|
||||||
scrollController: ScrollController(),
|
scrollController: ScrollController(),
|
||||||
phantomController: widget.phantomController,
|
phantomController: widget.phantomController,
|
||||||
onReorder: widget.dataController.moveColumnItem,
|
onReorder: widget.dataController.moveGroupItem,
|
||||||
cornerRadius: widget.config.cornerRadius,
|
cornerRadius: widget.config.cornerRadius,
|
||||||
backgroundColor: widget.config.columnBackgroundColor,
|
backgroundColor: widget.config.groupBackgroundColor,
|
||||||
dragStateStorage: widget.columnsState,
|
dragStateStorage: widget.columnsState,
|
||||||
dragTargetIndexKeyStorage: widget.columnsState,
|
dragTargetIndexKeyStorage: widget.columnsState,
|
||||||
);
|
);
|
||||||
|
|
||||||
widget.columnsState.addColumn(columnData.id, boardColumn);
|
widget.columnsState.addGroup(columnData.id, boardColumn);
|
||||||
|
|
||||||
return ConstrainedBox(
|
return ConstrainedBox(
|
||||||
constraints: widget.columnConstraints,
|
constraints: widget.columnConstraints,
|
||||||
child: boardColumn,
|
child: boardColumn,
|
||||||
@ -282,79 +297,79 @@ class _AFBoardContentState extends State<AFBoardContent> {
|
|||||||
|
|
||||||
Widget? _buildHeader(
|
Widget? _buildHeader(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
AFBoardColumnData columnData,
|
AppFlowyBoardGroupData groupData,
|
||||||
) {
|
) {
|
||||||
if (widget.headerBuilder == null) {
|
if (widget.headerBuilder == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return Selector<AFBoardColumnDataController, AFBoardColumnHeaderData>(
|
return Selector<AFBoardGroupDataController, AppFlowyBoardGroupHeaderData>(
|
||||||
selector: (context, controller) => controller.columnData.headerData,
|
selector: (context, controller) => controller.groupData.headerData,
|
||||||
builder: (context, headerData, _) {
|
builder: (context, headerData, _) {
|
||||||
return widget.headerBuilder!(context, columnData)!;
|
return widget.headerBuilder!(context, groupData)!;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeInsets _marginFromIndex(int index) {
|
EdgeInsets _marginFromIndex(int index) {
|
||||||
if (widget.dataController.columnDatas.isEmpty) {
|
if (widget.dataController.groupDatas.isEmpty) {
|
||||||
return widget.config.columnPadding;
|
return widget.config.groupPadding;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
return EdgeInsets.only(right: widget.config.columnPadding.right);
|
return EdgeInsets.only(right: widget.config.groupPadding.right);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == widget.dataController.columnDatas.length - 1) {
|
if (index == widget.dataController.groupDatas.length - 1) {
|
||||||
return EdgeInsets.only(left: widget.config.columnPadding.left);
|
return EdgeInsets.only(left: widget.config.groupPadding.left);
|
||||||
}
|
}
|
||||||
|
|
||||||
return widget.config.columnPadding;
|
return widget.config.groupPadding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _BoardColumnDataSourceImpl extends AFBoardColumnDataDataSource {
|
class _BoardGroupDataSourceImpl extends AppFlowyBoardGroupDataDataSource {
|
||||||
String columnId;
|
String groupId;
|
||||||
final AFBoardDataController dataController;
|
final AppFlowyBoardDataController dataController;
|
||||||
|
|
||||||
_BoardColumnDataSourceImpl({
|
_BoardGroupDataSourceImpl({
|
||||||
required this.columnId,
|
required this.groupId,
|
||||||
required this.dataController,
|
required this.dataController,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
AFBoardColumnData get columnData =>
|
AppFlowyBoardGroupData get groupData =>
|
||||||
dataController.getColumnController(columnId)!.columnData;
|
dataController.getGroupController(groupId)!.groupData;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<String> get acceptedColumnIds => dataController.columnIds;
|
List<String> get acceptedGroupIds => dataController.groupIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
class BoardColumnContext {
|
class BoardGroupContext {
|
||||||
GlobalKey? columnKey;
|
GlobalKey? groupKey;
|
||||||
DraggingState? draggingState;
|
DraggingState? draggingState;
|
||||||
}
|
}
|
||||||
|
|
||||||
class BoardColumnsState extends DraggingStateStorage
|
class BoardGroupsState extends DraggingStateStorage
|
||||||
with ReorderDragTargetIndexKeyStorage {
|
with ReorderDragTargetIndexKeyStorage {
|
||||||
/// Quick access to the [AFBoardColumnWidget]
|
/// Quick access to the [AppFlowyBoardGroupWidget]
|
||||||
final Map<String, GlobalKey> columnKeys = {};
|
final Map<String, GlobalKey> groupKeys = {};
|
||||||
final Map<String, DraggingState> columnDragStates = {};
|
final Map<String, DraggingState> groupDragStates = {};
|
||||||
final Map<String, Map<String, GlobalObjectKey>> columnDragDragTargets = {};
|
final Map<String, Map<String, GlobalObjectKey>> groupDragDragTargets = {};
|
||||||
|
|
||||||
void addColumn(String columnId, AFBoardColumnWidget columnWidget) {
|
void addGroup(String groupId, AppFlowyBoardGroupWidget groupWidget) {
|
||||||
columnKeys[columnId] = columnWidget.globalKey;
|
groupKeys[groupId] = groupWidget.reorderFlexKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReorderFlexState? getReorderFlexState({required String columnId}) {
|
ReorderFlexState? getReorderFlexState({required String groupId}) {
|
||||||
final flexGlobalKey = columnKeys[columnId];
|
final flexGlobalKey = groupKeys[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;
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReorderFlex? getReorderFlex({required String columnId}) {
|
ReorderFlex? getReorderFlex({required String groupId}) {
|
||||||
final flexGlobalKey = columnKeys[columnId];
|
final flexGlobalKey = groupKeys[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;
|
||||||
@ -363,18 +378,18 @@ class BoardColumnsState extends DraggingStateStorage
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
DraggingState? read(String reorderFlexId) {
|
DraggingState? read(String reorderFlexId) {
|
||||||
return columnDragStates[reorderFlexId];
|
return groupDragStates[reorderFlexId];
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void write(String reorderFlexId, DraggingState state) {
|
void write(String reorderFlexId, DraggingState state) {
|
||||||
Log.trace('$reorderFlexId Write dragging state: $state');
|
Log.trace('$reorderFlexId Write dragging state: $state');
|
||||||
columnDragStates[reorderFlexId] = state;
|
groupDragStates[reorderFlexId] = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void remove(String reorderFlexId) {
|
void remove(String reorderFlexId) {
|
||||||
columnDragStates.remove(reorderFlexId);
|
groupDragStates.remove(reorderFlexId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -383,20 +398,20 @@ class BoardColumnsState extends DraggingStateStorage
|
|||||||
String key,
|
String key,
|
||||||
GlobalObjectKey<State<StatefulWidget>> value,
|
GlobalObjectKey<State<StatefulWidget>> value,
|
||||||
) {
|
) {
|
||||||
Map<String, GlobalObjectKey>? column = columnDragDragTargets[reorderFlexId];
|
Map<String, GlobalObjectKey>? group = groupDragDragTargets[reorderFlexId];
|
||||||
if (column == null) {
|
if (group == null) {
|
||||||
column = {};
|
group = {};
|
||||||
columnDragDragTargets[reorderFlexId] = column;
|
groupDragDragTargets[reorderFlexId] = group;
|
||||||
}
|
}
|
||||||
column[key] = value;
|
group[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
GlobalObjectKey<State<StatefulWidget>>? readKey(
|
GlobalObjectKey<State<StatefulWidget>>? readKey(
|
||||||
String reorderFlexId, String key) {
|
String reorderFlexId, String key) {
|
||||||
Map<String, GlobalObjectKey>? column = columnDragDragTargets[reorderFlexId];
|
Map<String, GlobalObjectKey>? group = groupDragDragTargets[reorderFlexId];
|
||||||
if (column != null) {
|
if (group != null) {
|
||||||
return column[key];
|
return group[key];
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -9,49 +9,49 @@ 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 'board_column_data.dart';
|
||||||
|
|
||||||
typedef OnColumnDragStarted = void Function(int index);
|
typedef OnGroupDragStarted = void Function(int index);
|
||||||
|
|
||||||
typedef OnColumnDragEnded = void Function(String listId);
|
typedef OnGroupDragEnded = void Function(String listId);
|
||||||
|
|
||||||
typedef OnColumnReorder = void Function(
|
typedef OnGroupReorder = void Function(
|
||||||
String listId,
|
String listId,
|
||||||
int fromIndex,
|
int fromIndex,
|
||||||
int toIndex,
|
int toIndex,
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef OnColumnDeleted = void Function(String listId, int deletedIndex);
|
typedef OnGroupDeleted = void Function(String listId, int deletedIndex);
|
||||||
|
|
||||||
typedef OnColumnInserted = void Function(String listId, int insertedIndex);
|
typedef OnGroupInserted = void Function(String listId, int insertedIndex);
|
||||||
|
|
||||||
typedef AFBoardColumnCardBuilder = Widget Function(
|
typedef AppFlowyBoardCardBuilder = Widget Function(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
AFBoardColumnData columnData,
|
AppFlowyBoardGroupData groupData,
|
||||||
AFColumnItem item,
|
AppFlowyGroupItem item,
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef AFBoardColumnHeaderBuilder = Widget? Function(
|
typedef AppFlowyBoardHeaderBuilder = Widget? Function(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
AFBoardColumnData columnData,
|
AppFlowyBoardGroupData groupData,
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef AFBoardColumnFooterBuilder = Widget Function(
|
typedef AppFlowyBoardFooterBuilder = Widget Function(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
AFBoardColumnData columnData,
|
AppFlowyBoardGroupData groupData,
|
||||||
);
|
);
|
||||||
|
|
||||||
abstract class AFBoardColumnDataDataSource extends ReoderFlexDataSource {
|
abstract class AppFlowyBoardGroupDataDataSource extends ReoderFlexDataSource {
|
||||||
AFBoardColumnData get columnData;
|
AppFlowyBoardGroupData get groupData;
|
||||||
|
|
||||||
List<String> get acceptedColumnIds;
|
List<String> get acceptedGroupIds;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get identifier => columnData.id;
|
String get identifier => groupData.id;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
UnmodifiableListView<AFColumnItem> get items => columnData.items;
|
UnmodifiableListView<AppFlowyGroupItem> get items => groupData.items;
|
||||||
|
|
||||||
void debugPrint() {
|
void debugPrint() {
|
||||||
String msg = '[$AFBoardColumnDataDataSource] $columnData data: ';
|
String msg = '[$AppFlowyBoardGroupDataDataSource] $groupData data: ';
|
||||||
for (var element in items) {
|
for (var element in items) {
|
||||||
msg = '$msg$element,';
|
msg = '$msg$element,';
|
||||||
}
|
}
|
||||||
@ -60,25 +60,25 @@ abstract class AFBoardColumnDataDataSource extends ReoderFlexDataSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [AFBoardColumnWidget] represents the column of the Board.
|
/// [AppFlowyBoardGroupWidget] represents the column of the Board.
|
||||||
///
|
///
|
||||||
class AFBoardColumnWidget extends StatefulWidget {
|
class AppFlowyBoardGroupWidget extends StatefulWidget {
|
||||||
final AFBoardColumnDataDataSource dataSource;
|
final AppFlowyBoardGroupDataDataSource dataSource;
|
||||||
final ScrollController? scrollController;
|
final ScrollController? scrollController;
|
||||||
final ReorderFlexConfig config;
|
final ReorderFlexConfig config;
|
||||||
final OnColumnDragStarted? onDragStarted;
|
final OnGroupDragStarted? onDragStarted;
|
||||||
final OnColumnReorder onReorder;
|
final OnGroupReorder onReorder;
|
||||||
final OnColumnDragEnded? onDragEnded;
|
final OnGroupDragEnded? onDragEnded;
|
||||||
|
|
||||||
final BoardPhantomController phantomController;
|
final BoardPhantomController phantomController;
|
||||||
|
|
||||||
String get columnId => dataSource.columnData.id;
|
String get groupId => dataSource.groupData.id;
|
||||||
|
|
||||||
final AFBoardColumnCardBuilder cardBuilder;
|
final AppFlowyBoardCardBuilder cardBuilder;
|
||||||
|
|
||||||
final AFBoardColumnHeaderBuilder? headerBuilder;
|
final AppFlowyBoardHeaderBuilder? headerBuilder;
|
||||||
|
|
||||||
final AFBoardColumnFooterBuilder? footBuilder;
|
final AppFlowyBoardFooterBuilder? footerBuilder;
|
||||||
|
|
||||||
final EdgeInsets margin;
|
final EdgeInsets margin;
|
||||||
|
|
||||||
@ -92,12 +92,13 @@ class AFBoardColumnWidget extends StatefulWidget {
|
|||||||
|
|
||||||
final ReorderDragTargetIndexKeyStorage? dragTargetIndexKeyStorage;
|
final ReorderDragTargetIndexKeyStorage? dragTargetIndexKeyStorage;
|
||||||
|
|
||||||
final GlobalObjectKey globalKey;
|
final GlobalObjectKey reorderFlexKey;
|
||||||
|
|
||||||
AFBoardColumnWidget({
|
const AppFlowyBoardGroupWidget({
|
||||||
Key? key,
|
Key? key,
|
||||||
|
required this.reorderFlexKey,
|
||||||
this.headerBuilder,
|
this.headerBuilder,
|
||||||
this.footBuilder,
|
this.footerBuilder,
|
||||||
required this.cardBuilder,
|
required this.cardBuilder,
|
||||||
required this.onReorder,
|
required this.onReorder,
|
||||||
required this.dataSource,
|
required this.dataSource,
|
||||||
@ -111,59 +112,59 @@ class AFBoardColumnWidget extends StatefulWidget {
|
|||||||
this.itemMargin = EdgeInsets.zero,
|
this.itemMargin = EdgeInsets.zero,
|
||||||
this.cornerRadius = 0.0,
|
this.cornerRadius = 0.0,
|
||||||
this.backgroundColor = Colors.transparent,
|
this.backgroundColor = Colors.transparent,
|
||||||
}) : globalKey = GlobalObjectKey(dataSource.columnData.id),
|
}) : config = const ReorderFlexConfig(setStateWhenEndDrag: false),
|
||||||
config = const ReorderFlexConfig(setStateWhenEndDrag: false),
|
|
||||||
super(key: key);
|
super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<AFBoardColumnWidget> createState() => _AFBoardColumnWidgetState();
|
State<AppFlowyBoardGroupWidget> createState() =>
|
||||||
|
_AppFlowyBoardGroupWidgetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AFBoardColumnWidgetState extends State<AFBoardColumnWidget> {
|
class _AppFlowyBoardGroupWidgetState extends State<AppFlowyBoardGroupWidget> {
|
||||||
final GlobalKey _columnOverlayKey =
|
final GlobalKey _columnOverlayKey =
|
||||||
GlobalKey(debugLabel: '$AFBoardColumnWidget overlay key');
|
GlobalKey(debugLabel: '$AppFlowyBoardGroupWidget overlay key');
|
||||||
late BoardOverlayEntry _overlayEntry;
|
late BoardOverlayEntry _overlayEntry;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_overlayEntry = BoardOverlayEntry(
|
_overlayEntry = BoardOverlayEntry(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
final children = widget.dataSource.columnData.items
|
final children = widget.dataSource.groupData.items
|
||||||
.map((item) => _buildWidget(context, item))
|
.map((item) => _buildWidget(context, item))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
final header =
|
final header =
|
||||||
widget.headerBuilder?.call(context, widget.dataSource.columnData);
|
widget.headerBuilder?.call(context, widget.dataSource.groupData);
|
||||||
|
|
||||||
final footer =
|
final footer =
|
||||||
widget.footBuilder?.call(context, widget.dataSource.columnData);
|
widget.footerBuilder?.call(context, widget.dataSource.groupData);
|
||||||
|
|
||||||
final interceptor = CrossReorderFlexDragTargetInterceptor(
|
final interceptor = CrossReorderFlexDragTargetInterceptor(
|
||||||
reorderFlexId: widget.columnId,
|
reorderFlexId: widget.groupId,
|
||||||
delegate: widget.phantomController,
|
delegate: widget.phantomController,
|
||||||
acceptedReorderFlexIds: widget.dataSource.acceptedColumnIds,
|
acceptedReorderFlexIds: widget.dataSource.acceptedGroupIds,
|
||||||
draggableTargetBuilder: PhantomDraggableBuilder(),
|
draggableTargetBuilder: PhantomDraggableBuilder(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget reorderFlex = ReorderFlex(
|
Widget reorderFlex = ReorderFlex(
|
||||||
key: widget.globalKey,
|
key: widget.reorderFlexKey,
|
||||||
dragStateStorage: widget.dragStateStorage,
|
dragStateStorage: widget.dragStateStorage,
|
||||||
dragTargetIndexKeyStorage: widget.dragTargetIndexKeyStorage,
|
dragTargetIndexKeyStorage: widget.dragTargetIndexKeyStorage,
|
||||||
scrollController: widget.scrollController,
|
scrollController: widget.scrollController,
|
||||||
config: widget.config,
|
config: widget.config,
|
||||||
onDragStarted: (index) {
|
onDragStarted: (index) {
|
||||||
widget.phantomController.columnStartDragging(widget.columnId);
|
widget.phantomController.groupStartDragging(widget.groupId);
|
||||||
widget.onDragStarted?.call(index);
|
widget.onDragStarted?.call(index);
|
||||||
},
|
},
|
||||||
onReorder: ((fromIndex, toIndex) {
|
onReorder: ((fromIndex, toIndex) {
|
||||||
if (widget.phantomController.isFromColumn(widget.columnId)) {
|
if (widget.phantomController.isFromGroup(widget.groupId)) {
|
||||||
widget.onReorder(widget.columnId, fromIndex, toIndex);
|
widget.onReorder(widget.groupId, fromIndex, toIndex);
|
||||||
widget.phantomController.transformIndex(fromIndex, toIndex);
|
widget.phantomController.transformIndex(fromIndex, toIndex);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
onDragEnded: () {
|
onDragEnded: () {
|
||||||
widget.phantomController.columnEndDragging(widget.columnId);
|
widget.phantomController.groupEndDragging(widget.groupId);
|
||||||
widget.onDragEnded?.call(widget.columnId);
|
widget.onDragEnded?.call(widget.groupId);
|
||||||
widget.dataSource.debugPrint();
|
widget.dataSource.debugPrint();
|
||||||
},
|
},
|
||||||
dataSource: widget.dataSource,
|
dataSource: widget.dataSource,
|
||||||
@ -171,6 +172,10 @@ class _AFBoardColumnWidgetState extends State<AFBoardColumnWidget> {
|
|||||||
children: children,
|
children: children,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
reorderFlex = Expanded(
|
||||||
|
child: Padding(padding: widget.itemMargin, child: reorderFlex),
|
||||||
|
);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
margin: widget.margin,
|
margin: widget.margin,
|
||||||
clipBehavior: Clip.hardEdge,
|
clipBehavior: Clip.hardEdge,
|
||||||
@ -181,9 +186,7 @@ class _AFBoardColumnWidgetState extends State<AFBoardColumnWidget> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
if (header != null) header,
|
if (header != null) header,
|
||||||
Expanded(
|
reorderFlex,
|
||||||
child: Padding(padding: widget.itemMargin, child: reorderFlex),
|
|
||||||
),
|
|
||||||
if (footer != null) footer,
|
if (footer != null) footer,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -202,15 +205,15 @@ class _AFBoardColumnWidgetState extends State<AFBoardColumnWidget> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildWidget(BuildContext context, AFColumnItem item) {
|
Widget _buildWidget(BuildContext context, AppFlowyGroupItem item) {
|
||||||
if (item is PhantomColumnItem) {
|
if (item is PhantomGroupItem) {
|
||||||
return PassthroughPhantomWidget(
|
return PassthroughPhantomWidget(
|
||||||
key: UniqueKey(),
|
key: UniqueKey(),
|
||||||
opacity: widget.config.draggingWidgetOpacity,
|
opacity: widget.config.draggingWidgetOpacity,
|
||||||
passthroughPhantomContext: item.phantomContext,
|
passthroughPhantomContext: item.phantomContext,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return widget.cardBuilder(context, widget.dataSource.columnData, item);
|
return widget.cardBuilder(context, widget.dataSource.groupData, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,14 @@ import 'package:flutter/material.dart';
|
|||||||
import '../../utils/log.dart';
|
import '../../utils/log.dart';
|
||||||
import '../reorder_flex/reorder_flex.dart';
|
import '../reorder_flex/reorder_flex.dart';
|
||||||
|
|
||||||
abstract class AFColumnItem extends ReoderFlexItem {
|
abstract class AppFlowyGroupItem extends ReoderFlexItem {
|
||||||
bool get isPhantom => false;
|
bool get isPhantom => false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => id;
|
String toString() => id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [AFBoardColumnDataController] is used to handle the [AFBoardColumnData].
|
/// [AFBoardGroupDataController] is used to handle the [AppFlowyBoardGroupData].
|
||||||
/// * 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,23 +20,23 @@ abstract class AFColumnItem extends ReoderFlexItem {
|
|||||||
///
|
///
|
||||||
/// All there operations will notify listeners by default.
|
/// All there operations will notify listeners by default.
|
||||||
///
|
///
|
||||||
class AFBoardColumnDataController extends ChangeNotifier with EquatableMixin {
|
class AFBoardGroupDataController extends ChangeNotifier with EquatableMixin {
|
||||||
final AFBoardColumnData columnData;
|
final AppFlowyBoardGroupData groupData;
|
||||||
|
|
||||||
AFBoardColumnDataController({
|
AFBoardGroupDataController({
|
||||||
required this.columnData,
|
required this.groupData,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => columnData.props;
|
List<Object?> get props => groupData.props;
|
||||||
|
|
||||||
/// Returns the readonly List<ColumnItem>
|
/// Returns the readonly List<AppFlowyGroupItem>
|
||||||
UnmodifiableListView<AFColumnItem> get items =>
|
UnmodifiableListView<AppFlowyGroupItem> get items =>
|
||||||
UnmodifiableListView(columnData.items);
|
UnmodifiableListView(groupData.items);
|
||||||
|
|
||||||
void updateColumnName(String newName) {
|
void updateGroupName(String newName) {
|
||||||
if (columnData.headerData.columnName != newName) {
|
if (groupData.headerData.groupName != newName) {
|
||||||
columnData.headerData.columnName = newName;
|
groupData.headerData.groupName = newName;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,19 +46,18 @@ class AFBoardColumnDataController extends ChangeNotifier with EquatableMixin {
|
|||||||
/// * [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.
|
||||||
///
|
///
|
||||||
AFColumnItem removeAt(int index, {bool notify = true}) {
|
AppFlowyGroupItem removeAt(int index, {bool notify = true}) {
|
||||||
assert(index >= 0);
|
assert(index >= 0);
|
||||||
|
|
||||||
Log.debug(
|
Log.debug('[$AFBoardGroupDataController] $groupData remove item at $index');
|
||||||
'[$AFBoardColumnDataController] $columnData remove item at $index');
|
final item = groupData._items.removeAt(index);
|
||||||
final item = columnData._items.removeAt(index);
|
|
||||||
if (notify) {
|
if (notify) {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeWhere(bool Function(AFColumnItem) condition) {
|
void removeWhere(bool Function(AppFlowyGroupItem) condition) {
|
||||||
final index = items.indexWhere(condition);
|
final index = items.indexWhere(condition);
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
removeAt(index);
|
removeAt(index);
|
||||||
@ -75,9 +74,9 @@ class AFBoardColumnDataController extends ChangeNotifier with EquatableMixin {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Log.debug(
|
Log.debug(
|
||||||
'[$AFBoardColumnDataController] $columnData move item from $fromIndex to $toIndex');
|
'[$AFBoardGroupDataController] $groupData move item from $fromIndex to $toIndex');
|
||||||
final item = columnData._items.removeAt(fromIndex);
|
final item = groupData._items.removeAt(fromIndex);
|
||||||
columnData._items.insert(toIndex, item);
|
groupData._items.insert(toIndex, item);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -86,18 +85,18 @@ class AFBoardColumnDataController extends ChangeNotifier with EquatableMixin {
|
|||||||
/// is true.
|
/// is true.
|
||||||
///
|
///
|
||||||
/// The default value of [notify] is true.
|
/// The default value of [notify] is true.
|
||||||
bool insert(int index, AFColumnItem item, {bool notify = true}) {
|
bool insert(int index, AppFlowyGroupItem item, {bool notify = true}) {
|
||||||
assert(index >= 0);
|
assert(index >= 0);
|
||||||
Log.debug(
|
Log.debug(
|
||||||
'[$AFBoardColumnDataController] $columnData insert $item at $index');
|
'[$AFBoardGroupDataController] $groupData insert $item at $index');
|
||||||
|
|
||||||
if (_containsItem(item)) {
|
if (_containsItem(item)) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
if (columnData._items.length > index) {
|
if (groupData._items.length > index) {
|
||||||
columnData._items.insert(index, item);
|
groupData._items.insert(index, item);
|
||||||
} else {
|
} else {
|
||||||
columnData._items.add(item);
|
groupData._items.add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notify) notifyListeners();
|
if (notify) notifyListeners();
|
||||||
@ -105,74 +104,75 @@ class AFBoardColumnDataController extends ChangeNotifier with EquatableMixin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool add(AFColumnItem item, {bool notify = true}) {
|
bool add(AppFlowyGroupItem item, {bool notify = true}) {
|
||||||
if (_containsItem(item)) {
|
if (_containsItem(item)) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
columnData._items.add(item);
|
groupData._items.add(item);
|
||||||
if (notify) notifyListeners();
|
if (notify) notifyListeners();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replace the item at index with the [newItem].
|
/// Replace the item at index with the [newItem].
|
||||||
void replace(int index, AFColumnItem newItem) {
|
void replace(int index, AppFlowyGroupItem newItem) {
|
||||||
if (columnData._items.isEmpty) {
|
if (groupData._items.isEmpty) {
|
||||||
columnData._items.add(newItem);
|
groupData._items.add(newItem);
|
||||||
Log.debug('[$AFBoardColumnDataController] $columnData add $newItem');
|
Log.debug('[$AFBoardGroupDataController] $groupData add $newItem');
|
||||||
} else {
|
} else {
|
||||||
if (index >= columnData._items.length) {
|
if (index >= groupData._items.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final removedItem = columnData._items.removeAt(index);
|
final removedItem = groupData._items.removeAt(index);
|
||||||
columnData._items.insert(index, newItem);
|
groupData._items.insert(index, newItem);
|
||||||
Log.debug(
|
Log.debug(
|
||||||
'[$AFBoardColumnDataController] $columnData replace $removedItem with $newItem at $index');
|
'[$AFBoardGroupDataController] $groupData replace $removedItem with $newItem at $index');
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void replaceOrInsertItem(AFColumnItem newItem) {
|
void replaceOrInsertItem(AppFlowyGroupItem newItem) {
|
||||||
final index = columnData._items.indexWhere((item) => item.id == newItem.id);
|
final index = groupData._items.indexWhere((item) => item.id == newItem.id);
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
columnData._items.removeAt(index);
|
groupData._items.removeAt(index);
|
||||||
columnData._items.insert(index, newItem);
|
groupData._items.insert(index, newItem);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
} else {
|
} else {
|
||||||
columnData._items.add(newItem);
|
groupData._items.add(newItem);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _containsItem(AFColumnItem item) {
|
bool _containsItem(AppFlowyGroupItem item) {
|
||||||
return columnData._items.indexWhere((element) => element.id == item.id) !=
|
return groupData._items.indexWhere((element) => element.id == item.id) !=
|
||||||
-1;
|
-1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [AFBoardColumnData] represents the data of each Column of the Board.
|
/// [AppFlowyBoardGroupData] represents the data of each group of the Board.
|
||||||
class AFBoardColumnData<CustomData> extends ReoderFlexItem with EquatableMixin {
|
class AppFlowyBoardGroupData<CustomData> extends ReoderFlexItem
|
||||||
|
with EquatableMixin {
|
||||||
@override
|
@override
|
||||||
final String id;
|
final String id;
|
||||||
AFBoardColumnHeaderData headerData;
|
AppFlowyBoardGroupHeaderData headerData;
|
||||||
final List<AFColumnItem> _items;
|
final List<AppFlowyGroupItem> _items;
|
||||||
final CustomData? customData;
|
final CustomData? customData;
|
||||||
|
|
||||||
AFBoardColumnData({
|
AppFlowyBoardGroupData({
|
||||||
this.customData,
|
this.customData,
|
||||||
required this.id,
|
required this.id,
|
||||||
required String name,
|
required String name,
|
||||||
List<AFColumnItem> items = const [],
|
List<AppFlowyGroupItem> items = const [],
|
||||||
}) : _items = items,
|
}) : _items = items,
|
||||||
headerData = AFBoardColumnHeaderData(
|
headerData = AppFlowyBoardGroupHeaderData(
|
||||||
columnId: id,
|
groupId: id,
|
||||||
columnName: name,
|
groupName: name,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Returns the readonly List<ColumnItem>
|
/// Returns the readonly List<AppFlowyGroupItem>
|
||||||
UnmodifiableListView<AFColumnItem> get items =>
|
UnmodifiableListView<AppFlowyGroupItem> get items =>
|
||||||
UnmodifiableListView([..._items]);
|
UnmodifiableListView([..._items]);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -180,13 +180,14 @@ class AFBoardColumnData<CustomData> extends ReoderFlexItem with EquatableMixin {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'Column:[$id]';
|
return 'Group:[$id]';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AFBoardColumnHeaderData {
|
class AppFlowyBoardGroupHeaderData {
|
||||||
String columnId;
|
String groupId;
|
||||||
String columnName;
|
String groupName;
|
||||||
|
|
||||||
AFBoardColumnHeaderData({required this.columnId, required this.columnName});
|
AppFlowyBoardGroupHeaderData(
|
||||||
|
{required this.groupId, required this.groupName});
|
||||||
}
|
}
|
||||||
|
@ -8,213 +8,213 @@ 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';
|
||||||
|
|
||||||
typedef OnMoveColumn = void Function(
|
typedef OnMoveGroup = void Function(
|
||||||
String fromColumnId,
|
String fromGroupId,
|
||||||
int fromIndex,
|
int fromIndex,
|
||||||
String toColumnId,
|
String toGroupId,
|
||||||
int toIndex,
|
int toIndex,
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef OnMoveColumnItem = void Function(
|
typedef OnMoveGroupItem = void Function(
|
||||||
String columnId,
|
String groupId,
|
||||||
int fromIndex,
|
int fromIndex,
|
||||||
int toIndex,
|
int toIndex,
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef OnMoveColumnItemToColumn = void Function(
|
typedef OnMoveGroupItemToGroup = void Function(
|
||||||
String fromColumnId,
|
String fromGroupId,
|
||||||
int fromIndex,
|
int fromIndex,
|
||||||
String toColumnId,
|
String toGroupId,
|
||||||
int toIndex,
|
int toIndex,
|
||||||
);
|
);
|
||||||
|
|
||||||
class AFBoardDataController extends ChangeNotifier
|
class AppFlowyBoardDataController extends ChangeNotifier
|
||||||
with EquatableMixin, BoardPhantomControllerDelegate, ReoderFlexDataSource {
|
with EquatableMixin, BoardPhantomControllerDelegate, ReoderFlexDataSource {
|
||||||
final List<AFBoardColumnData> _columnDatas = [];
|
final List<AppFlowyBoardGroupData> _groupDatas = [];
|
||||||
final OnMoveColumn? onMoveColumn;
|
final OnMoveGroup? onMoveGroup;
|
||||||
final OnMoveColumnItem? onMoveColumnItem;
|
final OnMoveGroupItem? onMoveGroupItem;
|
||||||
final OnMoveColumnItemToColumn? onMoveColumnItemToColumn;
|
final OnMoveGroupItemToGroup? onMoveGroupItemToGroup;
|
||||||
|
|
||||||
List<AFBoardColumnData> get columnDatas => _columnDatas;
|
UnmodifiableListView<AppFlowyBoardGroupData> get groupDatas =>
|
||||||
|
UnmodifiableListView(_groupDatas);
|
||||||
|
|
||||||
List<String> get columnIds =>
|
List<String> get groupIds =>
|
||||||
_columnDatas.map((columnData) => columnData.id).toList();
|
_groupDatas.map((groupData) => groupData.id).toList();
|
||||||
|
|
||||||
final LinkedHashMap<String, AFBoardColumnDataController> _columnControllers =
|
final LinkedHashMap<String, AFBoardGroupDataController> _groupControllers =
|
||||||
LinkedHashMap();
|
LinkedHashMap();
|
||||||
|
|
||||||
AFBoardDataController({
|
AppFlowyBoardDataController({
|
||||||
this.onMoveColumn,
|
this.onMoveGroup,
|
||||||
this.onMoveColumnItem,
|
this.onMoveGroupItem,
|
||||||
this.onMoveColumnItemToColumn,
|
this.onMoveGroupItemToGroup,
|
||||||
});
|
});
|
||||||
|
|
||||||
void addColumn(AFBoardColumnData columnData, {bool notify = true}) {
|
void addGroup(AppFlowyBoardGroupData groupData, {bool notify = true}) {
|
||||||
if (_columnControllers[columnData.id] != null) return;
|
if (_groupControllers[groupData.id] != null) return;
|
||||||
|
|
||||||
final controller = AFBoardColumnDataController(columnData: columnData);
|
final controller = AFBoardGroupDataController(groupData: groupData);
|
||||||
_columnDatas.add(columnData);
|
_groupDatas.add(groupData);
|
||||||
_columnControllers[columnData.id] = controller;
|
_groupControllers[groupData.id] = controller;
|
||||||
if (notify) notifyListeners();
|
if (notify) notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void addColumns(List<AFBoardColumnData> columns, {bool notify = true}) {
|
void addGroups(List<AppFlowyBoardGroupData> groups, {bool notify = true}) {
|
||||||
for (final column in columns) {
|
for (final column in groups) {
|
||||||
addColumn(column, notify: false);
|
addGroup(column, notify: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (columns.isNotEmpty && notify) notifyListeners();
|
if (groups.isNotEmpty && notify) notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeColumn(String columnId, {bool notify = true}) {
|
void removeGroup(String groupId, {bool notify = true}) {
|
||||||
final index = _columnDatas.indexWhere((column) => column.id == columnId);
|
final index = _groupDatas.indexWhere((group) => group.id == groupId);
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
Log.warn(
|
Log.warn(
|
||||||
'Try to remove Column:[$columnId] failed. Column:[$columnId] not exist');
|
'Try to remove Group:[$groupId] failed. Group:[$groupId] not exist');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
_columnDatas.removeAt(index);
|
_groupDatas.removeAt(index);
|
||||||
_columnControllers.remove(columnId);
|
_groupControllers.remove(groupId);
|
||||||
|
|
||||||
if (notify) notifyListeners();
|
if (notify) notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeColumns(List<String> columnIds, {bool notify = true}) {
|
void removeGroups(List<String> groupIds, {bool notify = true}) {
|
||||||
for (final columnId in columnIds) {
|
for (final groupId in groupIds) {
|
||||||
removeColumn(columnId, notify: false);
|
removeGroup(groupId, notify: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (columnIds.isNotEmpty && notify) notifyListeners();
|
if (groupIds.isNotEmpty && notify) notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
_columnDatas.clear();
|
_groupDatas.clear();
|
||||||
_columnControllers.clear();
|
_groupControllers.clear();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
AFBoardColumnDataController? getColumnController(String columnId) {
|
AFBoardGroupDataController? getGroupController(String groupId) {
|
||||||
final columnController = _columnControllers[columnId];
|
final groupController = _groupControllers[groupId];
|
||||||
if (columnController == null) {
|
if (groupController == null) {
|
||||||
Log.warn('Column:[$columnId] \'s controller is not exist');
|
Log.warn('Group:[$groupId] \'s controller is not exist');
|
||||||
}
|
}
|
||||||
|
|
||||||
return columnController;
|
return groupController;
|
||||||
}
|
}
|
||||||
|
|
||||||
void moveColumn(int fromIndex, int toIndex, {bool notify = true}) {
|
void moveGroup(int fromIndex, int toIndex, {bool notify = true}) {
|
||||||
final toColumnData = _columnDatas[toIndex];
|
final toGroupData = _groupDatas[toIndex];
|
||||||
final fromColumnData = _columnDatas.removeAt(fromIndex);
|
final fromGroupData = _groupDatas.removeAt(fromIndex);
|
||||||
|
|
||||||
_columnDatas.insert(toIndex, fromColumnData);
|
_groupDatas.insert(toIndex, fromGroupData);
|
||||||
onMoveColumn?.call(fromColumnData.id, fromIndex, toColumnData.id, toIndex);
|
onMoveGroup?.call(fromGroupData.id, fromIndex, toGroupData.id, toIndex);
|
||||||
if (notify) notifyListeners();
|
if (notify) notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void moveColumnItem(String columnId, int fromIndex, int toIndex) {
|
void moveGroupItem(String groupId, int fromIndex, int toIndex) {
|
||||||
if (getColumnController(columnId)?.move(fromIndex, toIndex) ?? false) {
|
if (getGroupController(groupId)?.move(fromIndex, toIndex) ?? false) {
|
||||||
onMoveColumnItem?.call(columnId, fromIndex, toIndex);
|
onMoveGroupItem?.call(groupId, fromIndex, toIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addColumnItem(String columnId, AFColumnItem item) {
|
void addGroupItem(String groupId, AppFlowyGroupItem item) {
|
||||||
getColumnController(columnId)?.add(item);
|
getGroupController(groupId)?.add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertColumnItem(String columnId, int index, AFColumnItem item) {
|
void insertGroupItem(String groupId, int index, AppFlowyGroupItem item) {
|
||||||
getColumnController(columnId)?.insert(index, item);
|
getGroupController(groupId)?.insert(index, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeColumnItem(String columnId, String itemId) {
|
void removeGroupItem(String groupId, String itemId) {
|
||||||
getColumnController(columnId)?.removeWhere((item) => item.id == itemId);
|
getGroupController(groupId)?.removeWhere((item) => item.id == itemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateColumnItem(String columnId, AFColumnItem item) {
|
void updateGroupItem(String groupId, AppFlowyGroupItem item) {
|
||||||
getColumnController(columnId)?.replaceOrInsertItem(item);
|
getGroupController(groupId)?.replaceOrInsertItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@protected
|
@protected
|
||||||
void swapColumnItem(
|
void swapGroupItem(
|
||||||
String fromColumnId,
|
String fromGroupId,
|
||||||
int fromColumnIndex,
|
int fromGroupIndex,
|
||||||
String toColumnId,
|
String toGroupId,
|
||||||
int toColumnIndex,
|
int toGroupIndex,
|
||||||
) {
|
) {
|
||||||
final fromColumnController = getColumnController(fromColumnId)!;
|
final fromGroupController = getGroupController(fromGroupId)!;
|
||||||
final toColumnController = getColumnController(toColumnId)!;
|
final toGroupController = getGroupController(toGroupId)!;
|
||||||
final item = fromColumnController.removeAt(fromColumnIndex);
|
final item = fromGroupController.removeAt(fromGroupIndex);
|
||||||
if (toColumnController.items.length > toColumnIndex) {
|
if (toGroupController.items.length > toGroupIndex) {
|
||||||
assert(toColumnController.items[toColumnIndex] is PhantomColumnItem);
|
assert(toGroupController.items[toGroupIndex] is PhantomGroupItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
toColumnController.replace(toColumnIndex, item);
|
toGroupController.replace(toGroupIndex, item);
|
||||||
onMoveColumnItemToColumn?.call(
|
onMoveGroupItemToGroup?.call(
|
||||||
fromColumnId,
|
fromGroupId,
|
||||||
fromColumnIndex,
|
fromGroupIndex,
|
||||||
toColumnId,
|
toGroupId,
|
||||||
toColumnIndex,
|
toGroupIndex,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props {
|
List<Object?> get props {
|
||||||
return [_columnDatas];
|
return [_groupDatas];
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
AFBoardColumnDataController? controller(String columnId) {
|
AFBoardGroupDataController? controller(String groupId) {
|
||||||
return _columnControllers[columnId];
|
return _groupControllers[groupId];
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get identifier => '$AFBoardDataController';
|
String get identifier => '$AppFlowyBoardDataController';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
UnmodifiableListView<ReoderFlexItem> get items =>
|
UnmodifiableListView<ReoderFlexItem> get items =>
|
||||||
UnmodifiableListView(_columnDatas);
|
UnmodifiableListView(_groupDatas);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@protected
|
@protected
|
||||||
bool removePhantom(String columnId) {
|
bool removePhantom(String groupId) {
|
||||||
final columnController = getColumnController(columnId);
|
final groupController = getGroupController(groupId);
|
||||||
if (columnController == null) {
|
if (groupController == null) {
|
||||||
Log.warn('Can not find the column controller with columnId: $columnId');
|
Log.warn('Can not find the group controller with groupId: $groupId');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final index = columnController.items.indexWhere((item) => item.isPhantom);
|
final index = groupController.items.indexWhere((item) => item.isPhantom);
|
||||||
final isExist = index != -1;
|
final isExist = index != -1;
|
||||||
if (isExist) {
|
if (isExist) {
|
||||||
columnController.removeAt(index);
|
groupController.removeAt(index);
|
||||||
|
|
||||||
Log.debug(
|
Log.debug(
|
||||||
'[$AFBoardDataController] Column:[$columnId] remove phantom, current count: ${columnController.items.length}');
|
'[$AppFlowyBoardDataController] Group:[$groupId] remove phantom, current count: ${groupController.items.length}');
|
||||||
}
|
}
|
||||||
return isExist;
|
return isExist;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@protected
|
@protected
|
||||||
void updatePhantom(String columnId, int newIndex) {
|
void updatePhantom(String groupId, int newIndex) {
|
||||||
final columnDataController = getColumnController(columnId)!;
|
final groupController = getGroupController(groupId)!;
|
||||||
final index =
|
final index = groupController.items.indexWhere((item) => item.isPhantom);
|
||||||
columnDataController.items.indexWhere((item) => item.isPhantom);
|
|
||||||
|
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
if (index != newIndex) {
|
if (index != newIndex) {
|
||||||
Log.trace(
|
Log.trace(
|
||||||
'[$BoardPhantomController] update $columnId:$index to $columnId:$newIndex');
|
'[$BoardPhantomController] update $groupId:$index to $groupId:$newIndex');
|
||||||
final item = columnDataController.removeAt(index, notify: false);
|
final item = groupController.removeAt(index, notify: false);
|
||||||
columnDataController.insert(newIndex, item, notify: false);
|
groupController.insert(newIndex, item, notify: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@protected
|
@protected
|
||||||
void insertPhantom(String columnId, int index, PhantomColumnItem item) {
|
void insertPhantom(String groupId, int index, PhantomGroupItem item) {
|
||||||
getColumnController(columnId)!.insert(index, item);
|
getGroupController(groupId)!.insert(index, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 BoardColumnsState columnsState;
|
final BoardGroupsState columnsState;
|
||||||
Timer? _delayOperation;
|
Timer? _delayOperation;
|
||||||
|
|
||||||
OverlappingDragTargetInterceptor({
|
OverlappingDragTargetInterceptor({
|
||||||
@ -81,7 +81,7 @@ class OverlappingDragTargetInterceptor extends DragTargetInterceptor {
|
|||||||
delegate.cancel();
|
delegate.cancel();
|
||||||
} else {
|
} else {
|
||||||
// Ignore the event if the dragTarget overlaps with the other column's dragTargets.
|
// Ignore the event if the dragTarget overlaps with the other column's dragTargets.
|
||||||
final columnKeys = columnsState.columnDragDragTargets[dragTargetId];
|
final columnKeys = columnsState.groupDragDragTargets[dragTargetId];
|
||||||
if (columnKeys != null) {
|
if (columnKeys != null) {
|
||||||
final keys = columnKeys.values.toList();
|
final keys = columnKeys.values.toList();
|
||||||
if (dragTargetData.isOverlapWithWidgets(keys)) {
|
if (dragTargetData.isOverlapWithWidgets(keys)) {
|
||||||
@ -102,7 +102,7 @@ class OverlappingDragTargetInterceptor extends DragTargetInterceptor {
|
|||||||
delegate.moveTo(dragTargetId, dragTargetData, index);
|
delegate.moveTo(dragTargetId, dragTargetData, index);
|
||||||
|
|
||||||
columnsState
|
columnsState
|
||||||
.getReorderFlexState(columnId: dragTargetId)
|
.getReorderFlexState(groupId: dragTargetId)
|
||||||
?.resetDragTargetIndex(index);
|
?.resetDragTargetIndex(index);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -165,13 +165,13 @@ class CrossReorderFlexDragTargetInterceptor extends DragTargetInterceptor {
|
|||||||
@override
|
@override
|
||||||
void onAccept(FlexDragTargetData dragTargetData) {
|
void onAccept(FlexDragTargetData dragTargetData) {
|
||||||
Log.trace(
|
Log.trace(
|
||||||
'[$CrossReorderFlexDragTargetInterceptor] Column:[$reorderFlexId] on onAccept');
|
'[$CrossReorderFlexDragTargetInterceptor] Group:[$reorderFlexId] on onAccept');
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onLeave(FlexDragTargetData dragTargetData) {
|
void onLeave(FlexDragTargetData dragTargetData) {
|
||||||
Log.trace(
|
Log.trace(
|
||||||
'[$CrossReorderFlexDragTargetInterceptor] Column:[$reorderFlexId] on leave');
|
'[$CrossReorderFlexDragTargetInterceptor] Group:[$reorderFlexId] on leave');
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -49,8 +49,8 @@ class ReorderFlexConfig {
|
|||||||
/// Determines if setSatte method needs to be called when the drag is complete.
|
/// Determines if setSatte method needs to be called when the drag is complete.
|
||||||
/// Default value is [true].
|
/// Default value is [true].
|
||||||
///
|
///
|
||||||
/// If the [ReorderFlex] will be rebuild after the [ReorderFlex]'s children
|
/// If the [ReorderFlex] needs to be rebuild after the [ReorderFlex] end dragging,
|
||||||
/// were changed, then the [setStateWhenEndDrag] should set to [false].
|
/// the [setStateWhenEndDrag] should set to [true].
|
||||||
final bool setStateWhenEndDrag;
|
final bool setStateWhenEndDrag;
|
||||||
|
|
||||||
final bool useMoveAnimation;
|
final bool useMoveAnimation;
|
||||||
@ -252,7 +252,7 @@ class ReorderFlexState extends State<ReorderFlex>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Log.trace(
|
Log.trace(
|
||||||
'Rebuild: Column:[${dragState.reorderFlexId}] ${dragState.toString()}, childIndex: $childIndex shiftedIndex: $shiftedIndex');
|
'Rebuild: Group:[${dragState.reorderFlexId}] ${dragState.toString()}, childIndex: $childIndex shiftedIndex: $shiftedIndex');
|
||||||
final currentIndex = dragState.currentIndex;
|
final currentIndex = dragState.currentIndex;
|
||||||
final dragPhantomIndex = dragState.phantomIndex;
|
final dragPhantomIndex = dragState.phantomIndex;
|
||||||
|
|
||||||
@ -368,7 +368,7 @@ class ReorderFlexState extends State<ReorderFlex>
|
|||||||
),
|
),
|
||||||
onDragStarted: (draggingWidget, draggingIndex, size) {
|
onDragStarted: (draggingWidget, draggingIndex, size) {
|
||||||
Log.debug(
|
Log.debug(
|
||||||
"[DragTarget] Column:[${widget.dataSource.identifier}] start dragging item at $draggingIndex");
|
"[DragTarget] Group:[${widget.dataSource.identifier}] start dragging item at $draggingIndex");
|
||||||
_startDragging(draggingWidget, draggingIndex, size);
|
_startDragging(draggingWidget, draggingIndex, size);
|
||||||
widget.onDragStarted?.call(draggingIndex);
|
widget.onDragStarted?.call(draggingIndex);
|
||||||
widget.dragStateStorage?.remove(widget.reorderFlexId);
|
widget.dragStateStorage?.remove(widget.reorderFlexId);
|
||||||
@ -379,7 +379,7 @@ class ReorderFlexState extends State<ReorderFlex>
|
|||||||
onDragEnded: (dragTargetData) {
|
onDragEnded: (dragTargetData) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
Log.debug(
|
Log.debug(
|
||||||
"[DragTarget]: Column:[${widget.dataSource.identifier}] end dragging");
|
"[DragTarget]: Group:[${widget.dataSource.identifier}] end dragging");
|
||||||
_notifier.updateDragTargetIndex(-1);
|
_notifier.updateDragTargetIndex(-1);
|
||||||
|
|
||||||
onDragEnded() {
|
onDragEnded() {
|
||||||
|
@ -8,30 +8,30 @@ import '../reorder_flex/drag_target_interceptor.dart';
|
|||||||
import 'phantom_state.dart';
|
import 'phantom_state.dart';
|
||||||
|
|
||||||
abstract class BoardPhantomControllerDelegate {
|
abstract class BoardPhantomControllerDelegate {
|
||||||
AFBoardColumnDataController? controller(String columnId);
|
AFBoardGroupDataController? controller(String groupId);
|
||||||
|
|
||||||
bool removePhantom(String columnId);
|
bool removePhantom(String groupId);
|
||||||
|
|
||||||
/// Insert the phantom into column
|
/// Insert the phantom into the group
|
||||||
///
|
///
|
||||||
/// * [toColumnId] id of the column
|
/// * [groupId] id of the group
|
||||||
/// * [phantomIndex] the phantom occupies index
|
/// * [phantomIndex] the phantom occupies index
|
||||||
void insertPhantom(
|
void insertPhantom(
|
||||||
String columnId,
|
String groupId,
|
||||||
int index,
|
int index,
|
||||||
PhantomColumnItem item,
|
PhantomGroupItem item,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Update the column's phantom index if it exists.
|
/// Update the group's phantom index if it exists.
|
||||||
/// [toColumnId] the id of the column
|
/// [toGroupId] the id of the group
|
||||||
/// [dragTargetIndex] the index of the dragTarget
|
/// [dragTargetIndex] the index of the dragTarget
|
||||||
void updatePhantom(String columnId, int newIndex);
|
void updatePhantom(String groupId, int newIndex);
|
||||||
|
|
||||||
void swapColumnItem(
|
void swapGroupItem(
|
||||||
String fromColumnId,
|
String fromGroupId,
|
||||||
int fromColumnIndex,
|
int fromGroupIndex,
|
||||||
String toColumnId,
|
String toGroupId,
|
||||||
int toColumnIndex,
|
int toGroupIndex,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,16 +39,16 @@ class BoardPhantomController extends OverlapDragTargetDelegate
|
|||||||
with CrossReorderFlexDragTargetDelegate {
|
with CrossReorderFlexDragTargetDelegate {
|
||||||
PhantomRecord? phantomRecord;
|
PhantomRecord? phantomRecord;
|
||||||
final BoardPhantomControllerDelegate delegate;
|
final BoardPhantomControllerDelegate delegate;
|
||||||
final BoardColumnsState columnsState;
|
final BoardGroupsState groupsState;
|
||||||
final phantomState = ColumnPhantomState();
|
final phantomState = GroupPhantomState();
|
||||||
BoardPhantomController({
|
BoardPhantomController({
|
||||||
required this.delegate,
|
required this.delegate,
|
||||||
required this.columnsState,
|
required this.groupsState,
|
||||||
});
|
});
|
||||||
|
|
||||||
bool isFromColumn(String columnId) {
|
bool isFromGroup(String groupId) {
|
||||||
if (phantomRecord != null) {
|
if (phantomRecord != null) {
|
||||||
return phantomRecord!.fromColumnId == columnId;
|
return phantomRecord!.fromGroupId == groupId;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -58,32 +58,32 @@ class BoardPhantomController extends OverlapDragTargetDelegate
|
|||||||
if (phantomRecord == null) {
|
if (phantomRecord == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert(phantomRecord!.fromColumnIndex == fromIndex);
|
assert(phantomRecord!.fromGroupIndex == fromIndex);
|
||||||
phantomRecord?.updateFromColumnIndex(toIndex);
|
phantomRecord?.updateFromGroupIndex(toIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void columnStartDragging(String columnId) {
|
void groupStartDragging(String groupId) {
|
||||||
phantomState.setColumnIsDragging(columnId, true);
|
phantomState.setGroupIsDragging(groupId, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove the phantom in the column when the column is end dragging.
|
/// Remove the phantom in the group when the group is end dragging.
|
||||||
void columnEndDragging(String columnId) {
|
void groupEndDragging(String groupId) {
|
||||||
phantomState.setColumnIsDragging(columnId, false);
|
phantomState.setGroupIsDragging(groupId, false);
|
||||||
|
|
||||||
if (phantomRecord == null) return;
|
if (phantomRecord == null) return;
|
||||||
|
|
||||||
final fromColumnId = phantomRecord!.fromColumnId;
|
final fromGroupId = phantomRecord!.fromGroupId;
|
||||||
final toColumnId = phantomRecord!.toColumnId;
|
final toGroupId = phantomRecord!.toGroupId;
|
||||||
if (fromColumnId == columnId) {
|
if (fromGroupId == groupId) {
|
||||||
phantomState.notifyDidRemovePhantom(toColumnId);
|
phantomState.notifyDidRemovePhantom(toGroupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phantomRecord!.toColumnId == columnId) {
|
if (phantomRecord!.toGroupId == groupId) {
|
||||||
delegate.swapColumnItem(
|
delegate.swapGroupItem(
|
||||||
fromColumnId,
|
fromGroupId,
|
||||||
phantomRecord!.fromColumnIndex,
|
phantomRecord!.fromGroupIndex,
|
||||||
toColumnId,
|
toGroupId,
|
||||||
phantomRecord!.toColumnIndex,
|
phantomRecord!.toGroupIndex,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Log.debug(
|
// Log.debug(
|
||||||
@ -92,16 +92,16 @@ class BoardPhantomController extends OverlapDragTargetDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove the phantom in the column if it contains phantom
|
/// Remove the phantom in the group if it contains phantom
|
||||||
void _removePhantom(String columnId) {
|
void _removePhantom(String groupId) {
|
||||||
if (delegate.removePhantom(columnId)) {
|
if (delegate.removePhantom(groupId)) {
|
||||||
phantomState.notifyDidRemovePhantom(columnId);
|
phantomState.notifyDidRemovePhantom(groupId);
|
||||||
phantomState.removeColumnListener(columnId);
|
phantomState.removeGroupListener(groupId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _insertPhantom(
|
void _insertPhantom(
|
||||||
String toColumnId,
|
String toGroupId,
|
||||||
FlexDragTargetData dragTargetData,
|
FlexDragTargetData dragTargetData,
|
||||||
int phantomIndex,
|
int phantomIndex,
|
||||||
) {
|
) {
|
||||||
@ -109,38 +109,38 @@ class BoardPhantomController extends OverlapDragTargetDelegate
|
|||||||
index: phantomIndex,
|
index: phantomIndex,
|
||||||
dragTargetData: dragTargetData,
|
dragTargetData: dragTargetData,
|
||||||
);
|
);
|
||||||
phantomState.addColumnListener(toColumnId, phantomContext);
|
phantomState.addGroupListener(toGroupId, phantomContext);
|
||||||
|
|
||||||
delegate.insertPhantom(
|
delegate.insertPhantom(
|
||||||
toColumnId,
|
toGroupId,
|
||||||
phantomIndex,
|
phantomIndex,
|
||||||
PhantomColumnItem(phantomContext),
|
PhantomGroupItem(phantomContext),
|
||||||
);
|
);
|
||||||
|
|
||||||
phantomState.notifyDidInsertPhantom(toColumnId, phantomIndex);
|
phantomState.notifyDidInsertPhantom(toGroupId, phantomIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset or initial the [PhantomRecord]
|
/// Reset or initial the [PhantomRecord]
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// * [columnId] the id of the column
|
/// * [groupId] the id of the group
|
||||||
/// * [dragTargetData]
|
/// * [dragTargetData]
|
||||||
/// * [dragTargetIndex]
|
/// * [dragTargetIndex]
|
||||||
///
|
///
|
||||||
void _resetPhantomRecord(
|
void _resetPhantomRecord(
|
||||||
String columnId,
|
String groupId,
|
||||||
FlexDragTargetData dragTargetData,
|
FlexDragTargetData dragTargetData,
|
||||||
int dragTargetIndex,
|
int dragTargetIndex,
|
||||||
) {
|
) {
|
||||||
// Log.debug(
|
// Log.debug(
|
||||||
// '[$BoardPhantomController] move Column:[${dragTargetData.reorderFlexId}]:${dragTargetData.draggingIndex} '
|
// '[$BoardPhantomController] move Group:[${dragTargetData.reorderFlexId}]:${dragTargetData.draggingIndex} '
|
||||||
// 'to Column:[$columnId]:$dragTargetIndex');
|
// 'to Group:[$groupId]:$dragTargetIndex');
|
||||||
|
|
||||||
phantomRecord = PhantomRecord(
|
phantomRecord = PhantomRecord(
|
||||||
toColumnId: columnId,
|
toGroupId: groupId,
|
||||||
toColumnIndex: dragTargetIndex,
|
toGroupIndex: dragTargetIndex,
|
||||||
fromColumnId: dragTargetData.reorderFlexId,
|
fromGroupId: dragTargetData.reorderFlexId,
|
||||||
fromColumnIndex: dragTargetData.draggingIndex,
|
fromGroupIndex: dragTargetData.draggingIndex,
|
||||||
);
|
);
|
||||||
Log.debug('[$BoardPhantomController] will move: $phantomRecord');
|
Log.debug('[$BoardPhantomController] will move: $phantomRecord');
|
||||||
}
|
}
|
||||||
@ -158,10 +158,10 @@ class BoardPhantomController extends OverlapDragTargetDelegate
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final isNewDragTarget = phantomRecord!.toColumnId != reorderFlexId;
|
final isNewDragTarget = phantomRecord!.toGroupId != reorderFlexId;
|
||||||
if (isNewDragTarget) {
|
if (isNewDragTarget) {
|
||||||
/// Remove the phantom when the dragTarget is moved from one column to another column.
|
/// Remove the phantom when the dragTarget is moved from one group to another group.
|
||||||
_removePhantom(phantomRecord!.toColumnId);
|
_removePhantom(phantomRecord!.toGroupId);
|
||||||
_resetPhantomRecord(reorderFlexId, dragTargetData, dragTargetIndex);
|
_resetPhantomRecord(reorderFlexId, dragTargetData, dragTargetIndex);
|
||||||
_insertPhantom(reorderFlexId, dragTargetData, dragTargetIndex);
|
_insertPhantom(reorderFlexId, dragTargetData, dragTargetIndex);
|
||||||
}
|
}
|
||||||
@ -177,9 +177,9 @@ class BoardPhantomController extends OverlapDragTargetDelegate
|
|||||||
phantomRecord?.updateInsertedIndex(dragTargetIndex);
|
phantomRecord?.updateInsertedIndex(dragTargetIndex);
|
||||||
|
|
||||||
assert(phantomRecord != null);
|
assert(phantomRecord != null);
|
||||||
if (phantomRecord!.toColumnId == reorderFlexId) {
|
if (phantomRecord!.toGroupId == reorderFlexId) {
|
||||||
/// Update the existing phantom index
|
/// Update the existing phantom index
|
||||||
delegate.updatePhantom(phantomRecord!.toColumnId, dragTargetIndex);
|
delegate.updatePhantom(phantomRecord!.toGroupId, dragTargetIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,8 +189,8 @@ class BoardPhantomController extends OverlapDragTargetDelegate
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove the phantom when the dragTarge is go back to the original column.
|
/// Remove the phantom when the dragTarge is go back to the original group.
|
||||||
_removePhantom(phantomRecord!.toColumnId);
|
_removePhantom(phantomRecord!.toGroupId);
|
||||||
phantomRecord = null;
|
phantomRecord = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,63 +215,63 @@ class BoardPhantomController extends OverlapDragTargetDelegate
|
|||||||
|
|
||||||
final controller = delegate.controller(dragTargetId);
|
final controller = delegate.controller(dragTargetId);
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
return controller.columnData.items.length;
|
return controller.groupData.items.length;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Use [PhantomRecord] to record where to remove the column item and where to
|
/// Use [PhantomRecord] to record where to remove the group item and where to
|
||||||
/// insert the column item.
|
/// insert the group item.
|
||||||
///
|
///
|
||||||
/// [fromColumnId] the column that phantom comes from
|
/// [fromGroupId] the group that phantom comes from
|
||||||
/// [fromColumnIndex] the index of the phantom from the original column
|
/// [fromGroupIndex] the index of the phantom from the original group
|
||||||
/// [toColumnId] the column that the phantom moves into
|
/// [toGroupId] the group that the phantom moves into
|
||||||
/// [toColumnIndex] the index of the phantom moves into the column
|
/// [toGroupIndex] the index of the phantom moves into the group
|
||||||
///
|
///
|
||||||
class PhantomRecord {
|
class PhantomRecord {
|
||||||
final String fromColumnId;
|
final String fromGroupId;
|
||||||
int fromColumnIndex;
|
int fromGroupIndex;
|
||||||
|
|
||||||
final String toColumnId;
|
final String toGroupId;
|
||||||
int toColumnIndex;
|
int toGroupIndex;
|
||||||
|
|
||||||
PhantomRecord({
|
PhantomRecord({
|
||||||
required this.toColumnId,
|
required this.toGroupId,
|
||||||
required this.toColumnIndex,
|
required this.toGroupIndex,
|
||||||
required this.fromColumnId,
|
required this.fromGroupId,
|
||||||
required this.fromColumnIndex,
|
required this.fromGroupIndex,
|
||||||
});
|
});
|
||||||
|
|
||||||
void updateFromColumnIndex(int index) {
|
void updateFromGroupIndex(int index) {
|
||||||
if (fromColumnIndex == index) {
|
if (fromGroupIndex == index) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fromColumnIndex = index;
|
fromGroupIndex = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateInsertedIndex(int index) {
|
void updateInsertedIndex(int index) {
|
||||||
if (toColumnIndex == index) {
|
if (toGroupIndex == index) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.debug(
|
Log.debug(
|
||||||
'[$PhantomRecord] Column:[$toColumnId] update position $toColumnIndex -> $index');
|
'[$PhantomRecord] Group:[$toGroupId] update position $toGroupIndex -> $index');
|
||||||
toColumnIndex = index;
|
toGroupIndex = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'Column:[$fromColumnId]:$fromColumnIndex to Column:[$toColumnId]:$toColumnIndex';
|
return 'Group:[$fromGroupId]:$fromGroupIndex to Group:[$toGroupId]:$toGroupIndex';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PhantomColumnItem extends AFColumnItem {
|
class PhantomGroupItem extends AppFlowyGroupItem {
|
||||||
final PassthroughPhantomContext phantomContext;
|
final PassthroughPhantomContext phantomContext;
|
||||||
|
|
||||||
PhantomColumnItem(PassthroughPhantomContext insertedPhantom)
|
PhantomGroupItem(PassthroughPhantomContext insertedPhantom)
|
||||||
: phantomContext = insertedPhantom;
|
: phantomContext = insertedPhantom;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -305,7 +305,8 @@ class PassthroughPhantomContext extends FakeDragTargetEventTrigger
|
|||||||
|
|
||||||
Widget? get draggingWidget => dragTargetData.draggingWidget;
|
Widget? get draggingWidget => dragTargetData.draggingWidget;
|
||||||
|
|
||||||
AFColumnItem get itemData => dragTargetData.reorderFlexItem as AFColumnItem;
|
AppFlowyGroupItem get itemData =>
|
||||||
|
dragTargetData.reorderFlexItem as AppFlowyGroupItem;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void Function(int?)? onInserted;
|
void Function(int?)? onInserted;
|
||||||
|
@ -1,48 +1,48 @@
|
|||||||
import 'phantom_controller.dart';
|
import 'phantom_controller.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class ColumnPhantomState {
|
class GroupPhantomState {
|
||||||
final _states = <String, ColumnState>{};
|
final _states = <String, GroupState>{};
|
||||||
|
|
||||||
void setColumnIsDragging(String columnId, bool isDragging) {
|
void setGroupIsDragging(String groupId, bool isDragging) {
|
||||||
_stateWithId(columnId).isDragging = isDragging;
|
_stateWithId(groupId).isDragging = isDragging;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isDragging(String columnId) {
|
bool isDragging(String groupId) {
|
||||||
return _stateWithId(columnId).isDragging;
|
return _stateWithId(groupId).isDragging;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addColumnListener(String columnId, PassthroughPhantomListener listener) {
|
void addGroupListener(String groupId, PassthroughPhantomListener listener) {
|
||||||
_stateWithId(columnId).notifier.addListener(
|
_stateWithId(groupId).notifier.addListener(
|
||||||
onInserted: (index) => listener.onInserted?.call(index),
|
onInserted: (index) => listener.onInserted?.call(index),
|
||||||
onDeleted: () => listener.onDragEnded?.call(),
|
onDeleted: () => listener.onDragEnded?.call(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeColumnListener(String columnId) {
|
void removeGroupListener(String groupId) {
|
||||||
_stateWithId(columnId).notifier.dispose();
|
_stateWithId(groupId).notifier.dispose();
|
||||||
_states.remove(columnId);
|
_states.remove(groupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void notifyDidInsertPhantom(String columnId, int index) {
|
void notifyDidInsertPhantom(String groupId, int index) {
|
||||||
_stateWithId(columnId).notifier.insert(index);
|
_stateWithId(groupId).notifier.insert(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void notifyDidRemovePhantom(String columnId) {
|
void notifyDidRemovePhantom(String groupId) {
|
||||||
_stateWithId(columnId).notifier.remove();
|
_stateWithId(groupId).notifier.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnState _stateWithId(String columnId) {
|
GroupState _stateWithId(String groupId) {
|
||||||
var state = _states[columnId];
|
var state = _states[groupId];
|
||||||
if (state == null) {
|
if (state == null) {
|
||||||
state = ColumnState();
|
state = GroupState();
|
||||||
_states[columnId] = state;
|
_states[groupId] = state;
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ColumnState {
|
class GroupState {
|
||||||
bool isDragging = false;
|
bool isDragging = false;
|
||||||
final notifier = PassthroughPhantomNotifier();
|
final notifier = PassthroughPhantomNotifier();
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class AppFlowyColumnItemCard extends StatefulWidget {
|
class AppFlowyGroupItemCard 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 AppFlowyColumnItemCard({
|
const AppFlowyGroupItemCard({
|
||||||
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 AppFlowyColumnItemCard extends StatefulWidget {
|
|||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<AppFlowyColumnItemCard> createState() => _AppFlowyColumnItemCardState();
|
State<AppFlowyGroupItemCard> createState() => _AppFlowyGroupItemCardState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppFlowyColumnItemCardState extends State<AppFlowyColumnItemCard> {
|
class _AppFlowyGroupItemCardState extends State<AppFlowyGroupItemCard> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
|
@ -2,14 +2,14 @@ import 'package:flutter/material.dart';
|
|||||||
|
|
||||||
typedef OnFooterAddButtonClick = void Function();
|
typedef OnFooterAddButtonClick = void Function();
|
||||||
|
|
||||||
class AppFlowyColumnFooter extends StatefulWidget {
|
class AppFlowyGroupFooter extends StatefulWidget {
|
||||||
final double height;
|
final double height;
|
||||||
final Widget? icon;
|
final Widget? icon;
|
||||||
final Widget? title;
|
final Widget? title;
|
||||||
final EdgeInsets margin;
|
final EdgeInsets margin;
|
||||||
final OnFooterAddButtonClick? onAddButtonClick;
|
final OnFooterAddButtonClick? onAddButtonClick;
|
||||||
|
|
||||||
const AppFlowyColumnFooter({
|
const AppFlowyGroupFooter({
|
||||||
this.icon,
|
this.icon,
|
||||||
this.title,
|
this.title,
|
||||||
this.margin = const EdgeInsets.symmetric(horizontal: 12),
|
this.margin = const EdgeInsets.symmetric(horizontal: 12),
|
||||||
@ -19,10 +19,10 @@ class AppFlowyColumnFooter extends StatefulWidget {
|
|||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<AppFlowyColumnFooter> createState() => _AppFlowyColumnFooterState();
|
State<AppFlowyGroupFooter> createState() => _AppFlowyGroupFooterState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppFlowyColumnFooterState extends State<AppFlowyColumnFooter> {
|
class _AppFlowyGroupFooterState extends State<AppFlowyGroupFooter> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
|||||||
typedef OnHeaderAddButtonClick = void Function();
|
typedef OnHeaderAddButtonClick = void Function();
|
||||||
typedef OnHeaderMoreButtonClick = void Function();
|
typedef OnHeaderMoreButtonClick = void Function();
|
||||||
|
|
||||||
class AppFlowyColumnHeader extends StatefulWidget {
|
class AppFlowyGroupHeader extends StatefulWidget {
|
||||||
final double height;
|
final double height;
|
||||||
final Widget? icon;
|
final Widget? icon;
|
||||||
final Widget? title;
|
final Widget? title;
|
||||||
@ -13,7 +13,7 @@ class AppFlowyColumnHeader extends StatefulWidget {
|
|||||||
final OnHeaderAddButtonClick? onAddButtonClick;
|
final OnHeaderAddButtonClick? onAddButtonClick;
|
||||||
final OnHeaderMoreButtonClick? onMoreButtonClick;
|
final OnHeaderMoreButtonClick? onMoreButtonClick;
|
||||||
|
|
||||||
const AppFlowyColumnHeader({
|
const AppFlowyGroupHeader({
|
||||||
required this.height,
|
required this.height,
|
||||||
this.icon,
|
this.icon,
|
||||||
this.title,
|
this.title,
|
||||||
@ -26,10 +26,10 @@ class AppFlowyColumnHeader extends StatefulWidget {
|
|||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<AppFlowyColumnHeader> createState() => _AppFlowyColumnHeaderState();
|
State<AppFlowyGroupHeader> createState() => _AppFlowyGroupHeaderState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppFlowyColumnHeaderState extends State<AppFlowyColumnHeader> {
|
class _AppFlowyGroupHeaderState extends State<AppFlowyGroupHeader> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
List<Widget> children = [];
|
List<Widget> children = [];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user