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