chore: update

This commit is contained in:
appflowy 2022-08-04 20:55:02 +08:00
parent 9ea4c8b260
commit e8dad2ef03
6 changed files with 193 additions and 186 deletions

View File

@ -3,3 +3,4 @@ library flowy_board;
export 'src/widgets/board_column/board_column.dart'; export 'src/widgets/board_column/board_column.dart';
export 'src/widgets/board_column/data_controller.dart'; export 'src/widgets/board_column/data_controller.dart';
export 'src/widgets/board.dart'; export 'src/widgets/board.dart';
export 'src/widgets/board_data.dart';

View File

@ -1,13 +1,10 @@
import 'dart:collection';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../flowy_board.dart';
import '../rendering/board_overlay.dart';
import 'flex/drag_target_inteceptor.dart'; import 'flex/drag_target_inteceptor.dart';
import 'flex/reorder_flex.dart'; import 'flex/reorder_flex.dart';
import 'phantom/phantom_controller.dart'; import 'phantom/phantom_controller.dart';
import '../../flowy_board.dart';
import '../rendering/board_overlay.dart';
class Board extends StatelessWidget { class Board extends StatelessWidget {
/// The direction to use as the main axis. /// The direction to use as the main axis.
@ -60,54 +57,17 @@ class Board extends StatelessWidget {
value: dataController, value: dataController,
child: Consumer<BoardDataController>( child: Consumer<BoardDataController>(
builder: (context, notifier, child) { builder: (context, notifier, child) {
List<Widget> children = dataController.columnDatas.map((columnData) { return BoardContent(
final controller = dataController.columnController(columnData.id); dataController: dataController,
return _buildColumn(
columnData.id,
dataController.columnIds,
controller,
);
}).toList();
return BoardColumnContainer(
onReorder: dataController.onReorder,
boardDataController: dataController,
background: background, background: background,
spacing: spacing, spacing: spacing,
delegate: phantomController, delegate: phantomController,
children: children, columnConstraints: columnConstraints,
); cardBuilder: cardBuilder,
}, footBuilder: footBuilder,
), headerBuilder: headerBuilder,
); phantomController: phantomController,
} onReorder: dataController.onReorder,
///
Widget _buildColumn(
String columnId,
List<String> acceptColumns,
BoardColumnDataController dataController,
) {
return ChangeNotifierProvider.value(
key: ValueKey(columnId),
value: dataController,
child: Consumer<BoardColumnDataController>(
builder: (context, value, child) {
return ConstrainedBox(
constraints: columnConstraints,
child: BoardColumnWidget(
headerBuilder: headerBuilder,
footBuilder: footBuilder,
cardBuilder: cardBuilder,
acceptedColumns: acceptColumns,
dataController: dataController,
scrollController: ScrollController(),
onReorder: (_, int fromIndex, int toIndex) {
dataController.move(fromIndex, toIndex);
},
phantomController: phantomController,
),
); );
}, },
), ),
@ -115,96 +75,73 @@ class Board extends StatelessWidget {
} }
} }
class BoardDataController extends ChangeNotifier class BoardContent extends StatefulWidget {
with EquatableMixin, BoardPhantomControllerDelegate, ReoderFlextDataSource {
final List<BoardColumnData> _columnDatas = [];
List<BoardColumnData> get columnDatas => _columnDatas;
List<String> get columnIds =>
_columnDatas.map((columnData) => columnData.id).toList();
final LinkedHashMap<String, BoardColumnDataController> _columnControllers =
LinkedHashMap();
BoardDataController();
void setColumnData(BoardColumnData columnData) {
final controller = BoardColumnDataController(columnData: columnData);
_columnDatas.add(columnData);
_columnControllers[columnData.id] = controller;
}
BoardColumnDataController columnController(String columnId) {
return _columnControllers[columnId]!;
}
void onReorder(int fromIndex, int toIndex) {
final columnData = _columnDatas.removeAt(fromIndex);
_columnDatas.insert(toIndex, columnData);
notifyListeners();
}
@override
List<Object?> get props {
return [_columnDatas];
}
@override
BoardColumnDataController? controller(String columnId) {
return _columnControllers[columnId];
}
@override
String get identifier => '$BoardDataController';
@override
List<ReoderFlexItem> get items => _columnDatas;
}
class BoardColumnContainer extends StatefulWidget {
final ScrollController? scrollController; final ScrollController? scrollController;
final OnDragStarted? onDragStarted; final OnDragStarted? onDragStarted;
final OnReorder onReorder; final OnReorder onReorder;
final OnDragEnded? onDragEnded; final OnDragEnded? onDragEnded;
final BoardDataController boardDataController; final BoardDataController dataController;
final List<Widget> children;
final Widget? background; final Widget? background;
final double spacing; final double spacing;
final ReorderFlexConfig config; final ReorderFlexConfig config;
final BoxConstraints columnConstraints;
///
final BoardColumnCardBuilder cardBuilder;
///
final BoardColumnHeaderBuilder? headerBuilder;
///
final BoardColumnFooterBuilder? footBuilder;
final OverlapReorderFlexDragTargetDelegate delegate; final OverlapReorderFlexDragTargetDelegate delegate;
const BoardColumnContainer({ final BoardPhantomController phantomController;
const BoardContent({
required this.onReorder, required this.onReorder,
required this.children,
required this.delegate, required this.delegate,
required this.boardDataController, required this.dataController,
this.onDragStarted, this.onDragStarted,
this.onDragEnded, this.onDragEnded,
this.scrollController, this.scrollController,
this.background, this.background,
this.spacing = 0.0, this.spacing = 0.0,
this.config = const ReorderFlexConfig(), this.config = const ReorderFlexConfig(),
required this.columnConstraints,
required this.cardBuilder,
this.footBuilder,
this.headerBuilder,
required this.phantomController,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@override @override
State<BoardColumnContainer> createState() => _BoardColumnContainerState(); State<BoardContent> createState() => _BoardContentState();
} }
class _BoardColumnContainerState extends State<BoardColumnContainer> { class _BoardContentState extends State<BoardContent> {
final GlobalKey _columnContainerOverlayKey = final GlobalKey _columnContainerOverlayKey =
GlobalKey(debugLabel: '$BoardColumnContainer overlay key'); GlobalKey(debugLabel: '$BoardContent overlay key');
late BoardOverlayEntry _overlayEntry; late BoardOverlayEntry _overlayEntry;
@override @override
void initState() { void initState() {
_overlayEntry = BoardOverlayEntry( _overlayEntry = BoardOverlayEntry(
builder: (BuildContext context) { builder: (BuildContext context) {
List<Widget> children =
widget.dataController.columnDatas.map((columnData) {
return _buildColumn(
columnData.id,
widget.dataController.columnIds,
widget.dataController.columnController(columnData.id),
);
}).toList();
final interceptor = OverlapReorderFlexDragTargetInteceptor( final interceptor = OverlapReorderFlexDragTargetInteceptor(
reorderFlexId: widget.boardDataController.identifier, reorderFlexId: widget.dataController.identifier,
acceptedReorderFlexId: widget.boardDataController.columnIds, acceptedReorderFlexId: widget.dataController.columnIds,
delegate: widget.delegate, delegate: widget.delegate,
); );
@ -215,14 +152,20 @@ class _BoardColumnContainerState extends State<BoardColumnContainer> {
onDragStarted: widget.onDragStarted, onDragStarted: widget.onDragStarted,
onReorder: widget.onReorder, onReorder: widget.onReorder,
onDragEnded: widget.onDragEnded, onDragEnded: widget.onDragEnded,
dataSource: widget.boardDataController, dataSource: widget.dataController,
direction: Axis.horizontal, direction: Axis.horizontal,
spacing: widget.spacing, spacing: widget.spacing,
interceptor: interceptor, interceptor: interceptor,
children: widget.children, children: children,
); );
return _wrapStack(reorderFlex); return Stack(
alignment: AlignmentDirectional.topStart,
children: [
if (widget.background != null) widget.background!,
reorderFlex,
],
);
}, },
opaque: false, opaque: false,
); );
@ -237,13 +180,33 @@ class _BoardColumnContainerState extends State<BoardColumnContainer> {
); );
} }
Widget _wrapStack(Widget child) { Widget _buildColumn(
return Stack( String columnId,
alignment: AlignmentDirectional.topStart, List<String> acceptColumns,
children: [ BoardColumnDataController dataController,
if (widget.background != null) widget.background!, ) {
child, return ChangeNotifierProvider.value(
], key: ValueKey(columnId),
value: dataController,
child: Consumer<BoardColumnDataController>(
builder: (context, value, child) {
return ConstrainedBox(
constraints: widget.columnConstraints,
child: BoardColumnWidget(
headerBuilder: widget.headerBuilder,
footBuilder: widget.footBuilder,
cardBuilder: widget.cardBuilder,
acceptedColumns: acceptColumns,
dataController: dataController,
scrollController: ScrollController(),
onReorder: (_, int fromIndex, int toIndex) {
dataController.move(fromIndex, toIndex);
},
phantomController: widget.phantomController,
),
);
},
),
); );
} }
} }

View File

@ -0,0 +1,55 @@
import 'dart:collection';
import 'package:equatable/equatable.dart';
import '../../flowy_board.dart';
import 'flex/reorder_flex.dart';
import 'package:flutter/material.dart';
import 'phantom/phantom_controller.dart';
class BoardDataController extends ChangeNotifier
with EquatableMixin, BoardPhantomControllerDelegate, ReoderFlextDataSource {
final List<BoardColumnData> _columnDatas = [];
List<BoardColumnData> get columnDatas => _columnDatas;
List<String> get columnIds =>
_columnDatas.map((columnData) => columnData.id).toList();
final LinkedHashMap<String, BoardColumnDataController> _columnControllers =
LinkedHashMap();
BoardDataController();
void setColumnData(BoardColumnData columnData) {
final controller = BoardColumnDataController(columnData: columnData);
_columnDatas.add(columnData);
_columnControllers[columnData.id] = controller;
}
BoardColumnDataController columnController(String columnId) {
return _columnControllers[columnId]!;
}
void onReorder(int fromIndex, int toIndex) {
final columnData = _columnDatas.removeAt(fromIndex);
_columnDatas.insert(toIndex, columnData);
notifyListeners();
}
@override
List<Object?> get props {
return [_columnDatas];
}
@override
BoardColumnDataController? controller(String columnId) {
return _columnControllers[columnId];
}
@override
String get identifier => '$BoardDataController';
@override
List<ReoderFlexItem> get items => _columnDatas;
}

View File

@ -16,15 +16,14 @@ abstract class ReorderFlexDragTargetInterceptor {
required int dragTargetIndex, required int dragTargetIndex,
}); });
void onAccept(FlexDragTargetData dragTargetData); void onAccept(FlexDragTargetData dragTargetData) {}
void onLeave(FlexDragTargetData dragTargetData); void onLeave(FlexDragTargetData dragTargetData) {}
ReorderFlexDraggableTargetBuilder? get draggableTargetBuilder; ReorderFlexDraggableTargetBuilder? get draggableTargetBuilder => null;
} }
abstract class OverlapReorderFlexDragTargetDelegate abstract class OverlapReorderFlexDragTargetDelegate {}
extends CrossReorderFlexDragTargetDelegate {}
class OverlapReorderFlexDragTargetInteceptor class OverlapReorderFlexDragTargetInteceptor
extends ReorderFlexDragTargetInterceptor { extends ReorderFlexDragTargetInterceptor {
@ -43,15 +42,6 @@ class OverlapReorderFlexDragTargetInteceptor
return acceptedReorderFlexId.contains(dragTargetData.reorderFlexId); return acceptedReorderFlexId.contains(dragTargetData.reorderFlexId);
} }
@override
ReorderFlexDraggableTargetBuilder? get draggableTargetBuilder => null;
@override
void onAccept(FlexDragTargetData dragTargetData) {}
@override
void onLeave(FlexDragTargetData dragTargetData) {}
@override @override
bool onWillAccept( bool onWillAccept(
{required BuildContext context, {required BuildContext context,
@ -59,10 +49,9 @@ class OverlapReorderFlexDragTargetInteceptor
required FlexDragTargetData dragTargetData, required FlexDragTargetData dragTargetData,
required String dragTargetId, required String dragTargetId,
required int dragTargetIndex}) { required int dragTargetIndex}) {
Log.trace('dragTargetData: $dragTargetData'); if (dragTargetId == dragTargetData.reorderFlexId) {
Log.trace('currentDragTargetId: $dragTargetId'); Log.debug('remove all phantom');
// }
Log.debug('Switch to $dragTargetId');
return true; return true;
} }
@ -70,12 +59,13 @@ class OverlapReorderFlexDragTargetInteceptor
abstract class CrossReorderFlexDragTargetDelegate { abstract class CrossReorderFlexDragTargetDelegate {
bool acceptNewDragTargetData( bool acceptNewDragTargetData(
String columnId, String reorderFlexId,
FlexDragTargetData dragTargetData, FlexDragTargetData dragTargetData,
int index, int index,
); );
void updateDragTargetData( void updateDragTargetData(
String columnId, String reorderFlexId,
FlexDragTargetData dragTargetData, FlexDragTargetData dragTargetData,
int index, int index,
); );
@ -149,10 +139,6 @@ class CrossReorderFlexDragTargetInterceptor
dragTargetData.draggingIndex, dragTargetData.draggingIndex,
dragTargetIndex, dragTargetIndex,
); );
} else {
Log.debug(
'[$CrossReorderFlexDragTargetInterceptor] move Column${dragTargetData.reorderFlexId}:${dragTargetData.draggingIndex} '
'to Column$reorderFlexId:$dragTargetIndex');
} }
return true; return true;

View File

@ -317,7 +317,8 @@ class ReorderFlexState extends State<ReorderFlex>
}, },
onWillAccept: (FlexDragTargetData dragTargetData) { onWillAccept: (FlexDragTargetData dragTargetData) {
assert(widget.dataSource.items.length > dragTargetIndex); assert(widget.dataSource.items.length > dragTargetIndex);
Log.debug(
'[$ReorderDragTarget] ${widget.dataSource.identifier} on will accept, count: ${widget.dataSource.items.length}');
if (_interceptDragTarget( if (_interceptDragTarget(
dragTargetData, dragTargetData,
(interceptor) => interceptor.onWillAccept( (interceptor) => interceptor.onWillAccept(
@ -330,8 +331,6 @@ class ReorderFlexState extends State<ReorderFlex>
)) { )) {
return true; return true;
} else { } else {
Log.debug(
'[$ReorderDragTarget] ${widget.dataSource.identifier} on will accept, count: ${widget.dataSource.items.length}');
final dragIndex = dragTargetData.draggingIndex; final dragIndex = dragTargetData.draggingIndex;
return onWillAccept(builderContext, dragIndex, dragTargetIndex); return onWillAccept(builderContext, dragIndex, dragTargetIndex);
} }

View File

@ -14,10 +14,8 @@ mixin ColumnDataPhantomMixim {
BoardColumnDataController? get; BoardColumnDataController? get;
} }
class BoardPhantomController class BoardPhantomController extends OverlapReorderFlexDragTargetDelegate
with with CrossReorderFlexDragTargetDelegate {
CrossReorderFlexDragTargetDelegate,
OverlapReorderFlexDragTargetDelegate {
final BoardPhantomControllerDelegate delegate; final BoardPhantomControllerDelegate delegate;
PhantomRecord? phantomRecord; PhantomRecord? phantomRecord;
@ -85,43 +83,6 @@ class BoardPhantomController
phantomRecord = null; phantomRecord = null;
} }
@override
bool acceptNewDragTargetData(
String columnId, FlexDragTargetData dragTargetData, int index) {
if (phantomRecord == null) {
_updatePhantomRecord(columnId, dragTargetData, index);
_insertPhantom(columnId, dragTargetData, index);
return true;
}
final isDifferentDragTarget = phantomRecord!.toColumnId != columnId;
Log.debug(
'[$BoardPhantomController] Set inserted column id: $columnId, different target: $isDifferentDragTarget');
if (isDifferentDragTarget) {
/// Remove the phantom in the previous column.
_removePhantom(phantomRecord!.toColumnId);
/// Update the record and insert the phantom to new column.
_updatePhantomRecord(columnId, dragTargetData, index);
_insertPhantom(columnId, dragTargetData, index);
}
return isDifferentDragTarget;
}
@override
void updateDragTargetData(
String columnId, FlexDragTargetData dragTargetData, int index) {
phantomRecord?.updateInsertedIndex(index);
assert(phantomRecord != null);
if (phantomRecord!.toColumnId == columnId) {
/// Update the existing phantom index
_updatePhantom(phantomRecord!.toColumnId, dragTargetData, index);
}
}
void _updatePhantom( void _updatePhantom(
String toColumnId, String toColumnId,
FlexDragTargetData dragTargetData, FlexDragTargetData dragTargetData,
@ -197,6 +158,10 @@ class BoardPhantomController
FlexDragTargetData dragTargetData, FlexDragTargetData dragTargetData,
int index, int index,
) { ) {
Log.debug(
'[$BoardPhantomController] move Column${dragTargetData.reorderFlexId}:${dragTargetData.draggingIndex} '
'to Column$columnId:$index');
phantomRecord = PhantomRecord( phantomRecord = PhantomRecord(
toColumnId: columnId, toColumnId: columnId,
toColumnIndex: index, toColumnIndex: index,
@ -205,6 +170,42 @@ class BoardPhantomController
fromColumnIndex: dragTargetData.draggingIndex, fromColumnIndex: dragTargetData.draggingIndex,
); );
} }
@override
bool acceptNewDragTargetData(
String reorderFlexId, FlexDragTargetData dragTargetData, int index) {
if (phantomRecord == null) {
_updatePhantomRecord(reorderFlexId, dragTargetData, index);
_insertPhantom(reorderFlexId, dragTargetData, index);
return false;
}
final isNewDragTarget = phantomRecord!.toColumnId != reorderFlexId;
Log.debug(
'[$BoardPhantomController] Set inserted column id: $reorderFlexId, is new target: $isNewDragTarget');
if (isNewDragTarget) {
/// Remove the phantom in the previous column.
_removePhantom(phantomRecord!.toColumnId);
/// Update the record and insert the phantom to new column.
_updatePhantomRecord(reorderFlexId, dragTargetData, index);
_insertPhantom(reorderFlexId, dragTargetData, index);
}
return isNewDragTarget;
}
@override
void updateDragTargetData(
String reorderFlexId, FlexDragTargetData dragTargetData, int index) {
phantomRecord?.updateInsertedIndex(index);
assert(phantomRecord != null);
if (phantomRecord!.toColumnId == reorderFlexId) {
/// Update the existing phantom index
_updatePhantom(phantomRecord!.toColumnId, dragTargetData, index);
}
}
} }
class PhantomRecord { class PhantomRecord {
@ -234,6 +235,8 @@ class PhantomRecord {
void updateInsertedIndex(int index) { void updateInsertedIndex(int index) {
if (toColumnIndex == index) { if (toColumnIndex == index) {
Log.info(
'[$PhantomRecord] Column$toColumnId toColumnIndex: $toColumnIndex, index: $index');
return; return;
} }