chore: add documentation

This commit is contained in:
appflowy 2022-08-05 23:53:50 +08:00
parent 9e4dbc53f7
commit 8ca1cc0a21
7 changed files with 114 additions and 128 deletions

View File

@ -95,7 +95,7 @@ class BoardContent extends StatefulWidget {
/// ///
final BoardColumnFooterBuilder? footBuilder; final BoardColumnFooterBuilder? footBuilder;
final OverlapReorderFlexDragTargetDelegate delegate; final OverlapDragTargetDelegate delegate;
final BoardPhantomController phantomController; final BoardPhantomController phantomController;
@ -122,15 +122,14 @@ class BoardContent extends StatefulWidget {
} }
class _BoardContentState extends State<BoardContent> { class _BoardContentState extends State<BoardContent> {
final GlobalKey _columnContainerOverlayKey = final GlobalKey _columnContainerOverlayKey = GlobalKey(debugLabel: '$BoardContent 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) {
final interceptor = OverlapReorderFlexDragTargetInteceptor( final interceptor = OverlappingDragTargetInteceptor(
reorderFlexId: widget.dataController.identifier, reorderFlexId: widget.dataController.identifier,
acceptedReorderFlexId: widget.dataController.columnIds, acceptedReorderFlexId: widget.dataController.columnIds,
delegate: widget.delegate, delegate: widget.delegate,
@ -216,8 +215,7 @@ class _BoardColumnDataSourceImpl extends BoardColumnDataDataSource {
}); });
@override @override
BoardColumnData get columnData => BoardColumnData get columnData => dataController.columnController(columnId).columnData;
dataController.columnController(columnId).columnData;
@override @override
List<String> get acceptedColumnIds => dataController.columnIds; List<String> get acceptedColumnIds => dataController.columnIds;

View File

@ -46,16 +46,12 @@ class DraggingState {
final String id; final String id;
/// The member of widget.children currently being dragged. /// The member of widget.children currently being dragged.
///
/// Null if no drag is underway.
Widget? _draggingWidget; Widget? _draggingWidget;
Widget? get draggingWidget => _draggingWidget; Widget? get draggingWidget => _draggingWidget;
/// The last computed size of the feedback widget being dragged. /// The last computed size of the feedback widget being dragged.
Size? _draggingFeedbackSize = Size.zero; Size? feedbackSize = Size.zero;
Size? get feedbackSize => _draggingFeedbackSize;
/// The location that the dragging widget occupied before it started to drag. /// The location that the dragging widget occupied before it started to drag.
int dragStartIndex = -1; int dragStartIndex = -1;
@ -79,15 +75,17 @@ class DraggingState {
DraggingState(this.id); DraggingState(this.id);
Size get dropAreaSize { Size get dropAreaSize {
if (_draggingFeedbackSize == null) { if (feedbackSize == null) {
return Size.zero; return Size.zero;
} }
return _draggingFeedbackSize! + return feedbackSize! + const Offset(_dropAreaMargin, _dropAreaMargin);
const Offset(_dropAreaMargin, _dropAreaMargin);
} }
void startDragging(Widget draggingWidget, int draggingWidgetIndex, void startDragging(
Size? draggingWidgetSize) { Widget draggingWidget,
int draggingWidgetIndex,
Size? draggingWidgetSize,
) {
/// ///
assert(draggingWidgetIndex >= 0); assert(draggingWidgetIndex >= 0);
@ -95,7 +93,7 @@ class DraggingState {
phantomIndex = draggingWidgetIndex; phantomIndex = draggingWidgetIndex;
dragStartIndex = draggingWidgetIndex; dragStartIndex = draggingWidgetIndex;
currentIndex = draggingWidgetIndex; currentIndex = draggingWidgetIndex;
_draggingFeedbackSize = draggingWidgetSize; feedbackSize = draggingWidgetSize;
} }
void endDragging() { void endDragging() {
@ -130,12 +128,10 @@ class DraggingState {
/// Set the currentIndex to nextIndex /// Set the currentIndex to nextIndex
void moveDragTargetToNext() { void moveDragTargetToNext() {
Log.trace('moveDragTargetToNext: $nextIndex');
currentIndex = nextIndex; currentIndex = nextIndex;
} }
void updateNextIndex(int index) { void updateNextIndex(int index) {
assert(index >= 0);
Log.trace('updateNextIndex: $index'); Log.trace('updateNextIndex: $index');
nextIndex = index; nextIndex = index;
} }

View File

@ -5,24 +5,18 @@ abstract class DragTargetData {
} }
abstract class ReorderFlexDraggableTargetBuilder { abstract class ReorderFlexDraggableTargetBuilder {
Widget? build<T extends DragTargetData>( Widget? build<T extends DragTargetData>(BuildContext context, Widget child, DragTargetOnStarted onDragStarted,
BuildContext context, DragTargetOnEnded<T> onDragEnded, DragTargetWillAccpet<T> onWillAccept);
Widget child,
DragTargetOnStarted onDragStarted,
DragTargetOnEnded<T> onDragEnded,
DragTargetWillAccpet<T> onWillAccept);
} }
/// ///
typedef DragTargetWillAccpet<T extends DragTargetData> = bool Function( typedef DragTargetWillAccpet<T extends DragTargetData> = bool Function(T dragTargetData);
T dragTargetData);
/// ///
typedef DragTargetOnStarted = void Function(Widget, int, Size?); typedef DragTargetOnStarted = void Function(Widget, int, Size?);
/// ///
typedef DragTargetOnEnded<T extends DragTargetData> = void Function( typedef DragTargetOnEnded<T extends DragTargetData> = void Function(T dragTargetData);
T dragTargetData);
/// [ReorderDragTarget] is a [DragTarget] that carries the index information of /// [ReorderDragTarget] is a [DragTarget] that carries the index information of
/// the child. /// the child.
@ -75,8 +69,7 @@ class ReorderDragTarget<T extends DragTargetData> extends StatefulWidget {
State<ReorderDragTarget<T>> createState() => _ReorderDragTargetState<T>(); State<ReorderDragTarget<T>> createState() => _ReorderDragTargetState<T>();
} }
class _ReorderDragTargetState<T extends DragTargetData> class _ReorderDragTargetState<T extends DragTargetData> extends State<ReorderDragTarget<T>> {
extends State<ReorderDragTarget<T>> {
/// Returns the dragTarget's size /// Returns the dragTarget's size
Size? _draggingFeedbackSize = Size.zero; Size? _draggingFeedbackSize = Size.zero;
@ -108,8 +101,7 @@ class _ReorderDragTargetState<T extends DragTargetData>
List<dynamic> rejectedCandidates, List<dynamic> rejectedCandidates,
) { ) {
Widget feedbackBuilder = Builder(builder: (BuildContext context) { Widget feedbackBuilder = Builder(builder: (BuildContext context) {
BoxConstraints contentSizeConstraints = BoxConstraints contentSizeConstraints = BoxConstraints.loose(_draggingFeedbackSize!);
BoxConstraints.loose(_draggingFeedbackSize!);
return _buildDraggableFeedback( return _buildDraggableFeedback(
context, context,
contentSizeConstraints, contentSizeConstraints,
@ -149,21 +141,19 @@ class _ReorderDragTargetState<T extends DragTargetData>
/// When the drag does not end inside a DragTarget widget, the /// When the drag does not end inside a DragTarget widget, the
/// drag fails, but we still reorder the widget to the last position it /// drag fails, but we still reorder the widget to the last position it
/// had been dragged to. /// had been dragged to.
onDraggableCanceled: (Velocity velocity, Offset offset) => onDraggableCanceled: (Velocity velocity, Offset offset) => widget.onDragEnded(widget.dragTargetData),
widget.onDragEnded(widget.dragTargetData),
child: widget.child, child: widget.child,
); );
return draggableWidget; return draggableWidget;
} }
Widget _buildDraggableFeedback( Widget _buildDraggableFeedback(BuildContext context, BoxConstraints constraints, Widget child) {
BuildContext context, BoxConstraints constraints, Widget child) {
return Transform( return Transform(
transform: Matrix4.rotationZ(0), transform: Matrix4.rotationZ(0),
alignment: FractionalOffset.topLeft, alignment: FractionalOffset.topLeft,
child: Material( child: Material(
elevation: 6.0, elevation: 2.0,
color: Colors.transparent, color: Colors.transparent,
borderRadius: BorderRadius.zero, borderRadius: BorderRadius.zero,
clipBehavior: Clip.hardEdge, clipBehavior: Clip.hardEdge,
@ -177,10 +167,6 @@ class DragAnimationController {
// How long an animation to reorder an element in the list takes. // How long an animation to reorder an element in the list takes.
final Duration reorderAnimationDuration; final Duration reorderAnimationDuration;
// How long an animation to scroll to an off-screen element in the
// list takes.
final Duration scrollAnimationDuration;
// This controls the entrance of the dragging widget into a new place. // This controls the entrance of the dragging widget into a new place.
late AnimationController entranceController; late AnimationController entranceController;
@ -190,14 +176,11 @@ class DragAnimationController {
DragAnimationController({ DragAnimationController({
required this.reorderAnimationDuration, required this.reorderAnimationDuration,
required this.scrollAnimationDuration,
required TickerProvider vsync, required TickerProvider vsync,
required void Function(AnimationStatus) entranceAnimateStatusChanged, required void Function(AnimationStatus) entranceAnimateStatusChanged,
}) { }) {
entranceController = AnimationController( entranceController = AnimationController(value: 1.0, vsync: vsync, duration: reorderAnimationDuration);
value: 1.0, vsync: vsync, duration: reorderAnimationDuration); phantomController = AnimationController(value: 0, vsync: vsync, duration: reorderAnimationDuration);
phantomController = AnimationController(
value: 0, vsync: vsync, duration: reorderAnimationDuration);
entranceController.addStatusListener(entranceAnimateStatusChanged); entranceController.addStatusListener(entranceAnimateStatusChanged);
} }
@ -234,9 +217,7 @@ class IgnorePointerWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final sizedChild = useIntrinsicSize final sizedChild = useIntrinsicSize ? child : SizedBox(width: 0.0, height: 0.0, child: child);
? child
: SizedBox(width: 0.0, height: 0.0, child: child);
return IgnorePointer( return IgnorePointer(
ignoring: true, ignoring: true,
child: Opacity( child: Opacity(
@ -276,10 +257,8 @@ class PhantomAnimateContorller {
required this.reorderAnimationDuration, required this.reorderAnimationDuration,
required void Function(AnimationStatus) appearAnimateStatusChanged, required void Function(AnimationStatus) appearAnimateStatusChanged,
}) { }) {
appearController = AnimationController( appearController = AnimationController(value: 1.0, vsync: vsync, duration: reorderAnimationDuration);
value: 1.0, vsync: vsync, duration: reorderAnimationDuration); disappearController = AnimationController(value: 0, vsync: vsync, duration: reorderAnimationDuration);
disappearController = AnimationController(
value: 0, vsync: vsync, duration: reorderAnimationDuration);
appearController.addStatusListener(appearAnimateStatusChanged); appearController.addStatusListener(appearAnimateStatusChanged);
} }
@ -333,8 +312,7 @@ class FakeDragTarget<T extends DragTargetData> extends StatefulWidget {
State<FakeDragTarget<T>> createState() => _FakeDragTargetState<T>(); State<FakeDragTarget<T>> createState() => _FakeDragTargetState<T>();
} }
class _FakeDragTargetState<T extends DragTargetData> class _FakeDragTargetState<T extends DragTargetData> extends State<FakeDragTarget<T>> {
extends State<FakeDragTarget<T>> {
bool isDragging = false; bool isDragging = false;
@override @override

View File

@ -5,9 +5,13 @@ import 'drag_state.dart';
import 'drag_target.dart'; import 'drag_target.dart';
import 'reorder_flex.dart'; import 'reorder_flex.dart';
abstract class ReorderFlexDragTargetInterceptor { /// [DragTargetInterceptor] is used to intercept the [DragTarget]'s
/// [onWillAccept], [OnAccept], and [onLeave] event.
abstract class DragTargetInterceptor {
/// Returns [yes] to receive the [DragTarget]'s event.
bool canHandler(FlexDragTargetData dragTargetData); bool canHandler(FlexDragTargetData dragTargetData);
/// Handle the [DragTarget]'s [onWillAccept] event.
bool onWillAccept({ bool onWillAccept({
required BuildContext context, required BuildContext context,
required ReorderFlexState reorderFlexState, required ReorderFlexState reorderFlexState,
@ -16,29 +20,36 @@ abstract class ReorderFlexDragTargetInterceptor {
required int dragTargetIndex, required int dragTargetIndex,
}); });
/// Handle the [DragTarget]'s [onAccept] event.
void onAccept(FlexDragTargetData dragTargetData) {} void onAccept(FlexDragTargetData dragTargetData) {}
/// Handle the [DragTarget]'s [onLeave] event.
void onLeave(FlexDragTargetData dragTargetData) {} void onLeave(FlexDragTargetData dragTargetData) {}
ReorderFlexDraggableTargetBuilder? get draggableTargetBuilder => null; ReorderFlexDraggableTargetBuilder? get draggableTargetBuilder => null;
} }
abstract class OverlapReorderFlexDragTargetDelegate { abstract class OverlapDragTargetDelegate {
void dragTargetDidDisappear(); void didReturnOriginalDragTarget();
bool acceptNewDragTargetData( void didCrossOtherDragTarget(
String reorderFlexId, String reorderFlexId,
FlexDragTargetData dragTargetData, FlexDragTargetData dragTargetData,
int dragTargetIndex, int dragTargetIndex,
); );
} }
class OverlapReorderFlexDragTargetInteceptor /// [OverlappingDragTargetInteceptor] is used to receive the overlapping
extends ReorderFlexDragTargetInterceptor { /// [DragTarget] event. If a [DragTarget] child is [DragTarget], it will
/// receive the [DragTarget] event when being dragged.
///
/// Receive the [DragTarget] event if the [acceptedReorderFlexId] contains
/// the passed in dragTarget' reorderFlexId.
class OverlappingDragTargetInteceptor extends DragTargetInterceptor {
final String reorderFlexId; final String reorderFlexId;
final List<String> acceptedReorderFlexId; final List<String> acceptedReorderFlexId;
final OverlapReorderFlexDragTargetDelegate delegate; final OverlapDragTargetDelegate delegate;
OverlapReorderFlexDragTargetInteceptor({ OverlappingDragTargetInteceptor({
required this.delegate, required this.delegate,
required this.reorderFlexId, required this.reorderFlexId,
required this.acceptedReorderFlexId, required this.acceptedReorderFlexId,
@ -57,9 +68,9 @@ class OverlapReorderFlexDragTargetInteceptor
required String dragTargetId, required String dragTargetId,
required int dragTargetIndex}) { required int dragTargetIndex}) {
if (dragTargetId == dragTargetData.reorderFlexId) { if (dragTargetId == dragTargetData.reorderFlexId) {
delegate.dragTargetDidDisappear(); delegate.didReturnOriginalDragTarget();
} else { } else {
delegate.acceptNewDragTargetData( delegate.didCrossOtherDragTarget(
dragTargetId, dragTargetId,
dragTargetData, dragTargetData,
dragTargetIndex, dragTargetIndex,
@ -84,8 +95,7 @@ abstract class CrossReorderFlexDragTargetDelegate {
); );
} }
class CrossReorderFlexDragTargetInterceptor class CrossReorderFlexDragTargetInterceptor extends DragTargetInterceptor {
extends ReorderFlexDragTargetInterceptor {
final String reorderFlexId; final String reorderFlexId;
final List<String> acceptedReorderFlexIds; final List<String> acceptedReorderFlexIds;
final CrossReorderFlexDragTargetDelegate delegate; final CrossReorderFlexDragTargetDelegate delegate;
@ -117,14 +127,12 @@ class CrossReorderFlexDragTargetInterceptor
@override @override
void onAccept(FlexDragTargetData dragTargetData) { void onAccept(FlexDragTargetData dragTargetData) {
Log.trace( Log.trace('[$CrossReorderFlexDragTargetInterceptor] Column$reorderFlexId on onAccept');
'[$CrossReorderFlexDragTargetInterceptor] Column$reorderFlexId on onAccept');
} }
@override @override
void onLeave(FlexDragTargetData dragTargetData) { void onLeave(FlexDragTargetData dragTargetData) {
Log.trace( Log.trace('[$CrossReorderFlexDragTargetInterceptor] Column$reorderFlexId on leave');
'[$CrossReorderFlexDragTargetInterceptor] Column$reorderFlexId on leave');
} }
@override @override

View File

@ -14,26 +14,34 @@ typedef OnDragEnded = void Function();
typedef OnReorder = void Function(int fromIndex, int toIndex); typedef OnReorder = void Function(int fromIndex, int toIndex);
typedef OnDeleted = void Function(int deletedIndex); typedef OnDeleted = void Function(int deletedIndex);
typedef OnInserted = void Function(int insertedIndex); typedef OnInserted = void Function(int insertedIndex);
typedef OnReveivePassedInPhantom = void Function( typedef OnReveivePassedInPhantom = void Function(FlexDragTargetData dragTargetData, int phantomIndex);
FlexDragTargetData dragTargetData, int phantomIndex);
abstract class ReoderFlextDataSource { abstract class ReoderFlextDataSource {
/// [identifier] represents the id the [ReorderFlex]. It must be unique.
String get identifier; String get identifier;
/// The number of [ReoderFlexItem]s will be displaied in the [ReorderFlex].
UnmodifiableListView<ReoderFlexItem> get items; UnmodifiableListView<ReoderFlexItem> get items;
} }
/// Each item displaied in the [ReorderFlex] required to implement the [ReoderFlexItem].
abstract class ReoderFlexItem { abstract class ReoderFlexItem {
/// [id] is used to identify the item /// [id] is used to identify the item. It must be unique.
String get id; String get id;
} }
class ReorderFlexConfig { class ReorderFlexConfig {
final bool needsLongPressDraggable = true; /// The opacity of the dragging widget
final double draggingWidgetOpacity = 0.2; final double draggingWidgetOpacity = 0.2;
// How long an animation to reorder an element
final Duration reorderAnimationDuration = const Duration(milliseconds: 250); final Duration reorderAnimationDuration = const Duration(milliseconds: 250);
// How long an animation to scroll to an off-screen element
final Duration scrollAnimationDuration = const Duration(milliseconds: 250); final Duration scrollAnimationDuration = const Duration(milliseconds: 250);
final double? spacing; final double? spacing;
const ReorderFlexConfig({this.spacing}); const ReorderFlexConfig({this.spacing});
} }
@ -42,17 +50,25 @@ class ReorderFlex extends StatefulWidget {
final List<Widget> children; final List<Widget> children;
final EdgeInsets? padding; final EdgeInsets? padding;
/// [direction] How to place the children, default is Axis.vertical
final Axis direction; final Axis direction;
final MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start; final MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start;
final ScrollController? scrollController; final ScrollController? scrollController;
/// [onDragStarted] is called when start dragging
final OnDragStarted? onDragStarted; final OnDragStarted? onDragStarted;
/// [onReorder] is called when dragTarget did end dragging
final OnReorder onReorder; final OnReorder onReorder;
/// [onDragEnded] is called when dragTarget did end dragging
final OnDragEnded? onDragEnded; final OnDragEnded? onDragEnded;
final ReoderFlextDataSource dataSource; final ReoderFlextDataSource dataSource;
final ReorderFlexDragTargetInterceptor? interceptor; final DragTargetInterceptor? interceptor;
const ReorderFlex({ const ReorderFlex({
Key? key, Key? key,
@ -74,16 +90,20 @@ class ReorderFlex extends StatefulWidget {
String get reorderFlexId => dataSource.identifier; String get reorderFlexId => dataSource.identifier;
} }
class ReorderFlexState extends State<ReorderFlex> class ReorderFlexState extends State<ReorderFlex> with ReorderFlexMinxi, TickerProviderStateMixin<ReorderFlex> {
with ReorderFlexMinxi, TickerProviderStateMixin<ReorderFlex> {
/// Controls scrolls and measures scroll progress. /// Controls scrolls and measures scroll progress.
late ScrollController _scrollController; late ScrollController _scrollController;
/// Records the position of the [Scrollable]
ScrollPosition? _attachedScrollPosition; ScrollPosition? _attachedScrollPosition;
/// Whether or not we are currently scrolling this view to show a widget. /// Whether or not we are currently scrolling this view to show a widget.
bool _scrolling = false; bool _scrolling = false;
/// [dragState] records the dragging state including dragStartIndex, and phantomIndex, etc.
late DraggingState dragState; late DraggingState dragState;
/// [_dragAnimationController] controls the dragging animations
late DragAnimationController _dragAnimationController; late DragAnimationController _dragAnimationController;
@override @override
@ -92,7 +112,6 @@ class ReorderFlexState extends State<ReorderFlex>
_dragAnimationController = DragAnimationController( _dragAnimationController = DragAnimationController(
reorderAnimationDuration: widget.config.reorderAnimationDuration, reorderAnimationDuration: widget.config.reorderAnimationDuration,
scrollAnimationDuration: widget.config.scrollAnimationDuration,
entranceAnimateStatusChanged: (status) { entranceAnimateStatusChanged: (status) {
if (status == AnimationStatus.completed) { if (status == AnimationStatus.completed) {
setState(() => _requestAnimationToNextIndex()); setState(() => _requestAnimationToNextIndex());
@ -111,9 +130,7 @@ class ReorderFlexState extends State<ReorderFlex>
_attachedScrollPosition = null; _attachedScrollPosition = null;
} }
_scrollController = widget.scrollController ?? _scrollController = widget.scrollController ?? PrimaryScrollController.of(context) ?? ScrollController();
PrimaryScrollController.of(context) ??
ScrollController();
if (_scrollController.hasClients) { if (_scrollController.hasClients) {
_attachedScrollPosition = Scrollable.of(context)?.position; _attachedScrollPosition = Scrollable.of(context)?.position;
@ -235,9 +252,7 @@ class ReorderFlexState extends State<ReorderFlex>
]); ]);
} else if (childIndex == dragPhantomIndex) { } else if (childIndex == dragPhantomIndex) {
return _buildDraggingContainer( return _buildDraggingContainer(
children: shiftedIndex <= childIndex children: shiftedIndex <= childIndex ? [dragTarget, disappearSpace] : [disappearSpace, dragTarget]);
? [dragTarget, disappearSpace]
: [disappearSpace, dragTarget]);
} }
} }
@ -258,9 +273,7 @@ class ReorderFlexState extends State<ReorderFlex>
]); ]);
} else if (childIndex == dragPhantomIndex) { } else if (childIndex == dragPhantomIndex) {
return _buildDraggingContainer( return _buildDraggingContainer(
children: shiftedIndex >= childIndex children: shiftedIndex >= childIndex ? [disappearSpace, dragTarget] : [dragTarget, disappearSpace]);
? [disappearSpace, dragTarget]
: [dragTarget, disappearSpace]);
} }
} }
@ -286,8 +299,7 @@ class ReorderFlexState extends State<ReorderFlex>
Widget child, Widget child,
int dragTargetIndex, int dragTargetIndex,
) { ) {
final ReoderFlexItem reorderFlexItem = final ReoderFlexItem reorderFlexItem = widget.dataSource.items[dragTargetIndex];
widget.dataSource.items[dragTargetIndex];
return ReorderDragTarget<FlexDragTargetData>( return ReorderDragTarget<FlexDragTargetData>(
dragTargetData: FlexDragTargetData( dragTargetData: FlexDragTargetData(
draggingIndex: dragTargetIndex, draggingIndex: dragTargetIndex,
@ -297,14 +309,12 @@ class ReorderFlexState extends State<ReorderFlex>
dragTargetId: reorderFlexItem.id, dragTargetId: reorderFlexItem.id,
), ),
onDragStarted: (draggingWidget, draggingIndex, size) { onDragStarted: (draggingWidget, draggingIndex, size) {
Log.debug( Log.debug("[DragTarget] Column${widget.dataSource.identifier} start dragging");
"[DragTarget] Column${widget.dataSource.identifier} start dragging");
_startDragging(draggingWidget, draggingIndex, size); _startDragging(draggingWidget, draggingIndex, size);
widget.onDragStarted?.call(draggingIndex); widget.onDragStarted?.call(draggingIndex);
}, },
onDragEnded: (dragTargetData) { onDragEnded: (dragTargetData) {
Log.debug( Log.debug("[DragTarget]: Column${widget.dataSource.identifier} end dragging");
"[DragTarget]: Column${widget.dataSource.identifier} end dragging");
setState(() { setState(() {
_onReordered( _onReordered(
@ -352,7 +362,7 @@ class ReorderFlexState extends State<ReorderFlex>
bool _interceptDragTarget( bool _interceptDragTarget(
FlexDragTargetData dragTargetData, FlexDragTargetData dragTargetData,
void Function(ReorderFlexDragTargetInterceptor) callback, void Function(DragTargetInterceptor) callback,
) { ) {
final interceptor = widget.interceptor; final interceptor = widget.interceptor;
if (interceptor != null && interceptor.canHandler(dragTargetData)) { if (interceptor != null && interceptor.canHandler(dragTargetData)) {
@ -401,8 +411,7 @@ class ReorderFlexState extends State<ReorderFlex>
Log.trace( Log.trace(
'[$ReorderDragTarget] ${widget.dataSource.identifier} on will accept, dragIndex:$dragIndex, dragTargetIndex:$dragTargetIndex, count: ${widget.dataSource.items.length}'); '[$ReorderDragTarget] ${widget.dataSource.identifier} on will accept, dragIndex:$dragIndex, dragTargetIndex:$dragTargetIndex, count: ${widget.dataSource.items.length}');
bool willAccept = bool willAccept = dragState.dragStartIndex == dragIndex && dragIndex != dragTargetIndex;
dragState.dragStartIndex == dragIndex && dragIndex != dragTargetIndex;
setState(() { setState(() {
if (willAccept) { if (willAccept) {
int shiftedIndex = dragState.calculateShiftedIndex(dragTargetIndex); int shiftedIndex = dragState.calculateShiftedIndex(dragTargetIndex);
@ -429,8 +438,7 @@ class ReorderFlexState extends State<ReorderFlex>
} }
Widget _wrapScrollView({required Widget child}) { Widget _wrapScrollView({required Widget child}) {
if (widget.scrollController != null && if (widget.scrollController != null && PrimaryScrollController.of(context) == null) {
PrimaryScrollController.of(context) == null) {
return child; return child;
} else { } else {
return SingleChildScrollView( return SingleChildScrollView(
@ -484,14 +492,12 @@ class ReorderFlexState extends State<ReorderFlex>
void _scrollTo(BuildContext context) { void _scrollTo(BuildContext context) {
if (_scrolling) return; if (_scrolling) return;
final RenderObject contextObject = context.findRenderObject()!; final RenderObject contextObject = context.findRenderObject()!;
final RenderAbstractViewport viewport = final RenderAbstractViewport viewport = RenderAbstractViewport.of(contextObject)!;
RenderAbstractViewport.of(contextObject)!;
// If and only if the current scroll offset falls in-between the offsets // If and only if the current scroll offset falls in-between the offsets
// necessary to reveal the selected context at the top or bottom of the // necessary to reveal the selected context at the top or bottom of the
// screen, then it is already on-screen. // screen, then it is already on-screen.
final double margin = widget.direction == Axis.horizontal final double margin =
? dragState.dropAreaSize.width widget.direction == Axis.horizontal ? dragState.dropAreaSize.width : dragState.dropAreaSize.height;
: dragState.dropAreaSize.height;
if (_scrollController.hasClients) { if (_scrollController.hasClients) {
final double scrollOffset = _scrollController.offset; final double scrollOffset = _scrollController.offset;
final double topOffset = max( final double topOffset = max(
@ -502,8 +508,7 @@ class ReorderFlexState extends State<ReorderFlex>
_scrollController.position.maxScrollExtent, _scrollController.position.maxScrollExtent,
viewport.getOffsetToReveal(contextObject, 1.0).offset + margin, viewport.getOffsetToReveal(contextObject, 1.0).offset + margin,
); );
final bool onScreen = final bool onScreen = scrollOffset <= topOffset && scrollOffset >= bottomOffset;
scrollOffset <= topOffset && scrollOffset >= bottomOffset;
// If the context is off screen, then we request a scroll to make it visible. // If the context is off screen, then we request a scroll to make it visible.
if (!onScreen) { if (!onScreen) {
@ -511,7 +516,7 @@ class ReorderFlexState extends State<ReorderFlex>
_scrollController.position _scrollController.position
.animateTo( .animateTo(
scrollOffset < bottomOffset ? bottomOffset : topOffset, scrollOffset < bottomOffset ? bottomOffset : topOffset,
duration: _dragAnimationController.scrollAnimationDuration, duration: widget.config.scrollAnimationDuration,
curve: Curves.easeInOut, curve: Curves.easeInOut,
) )
.then((void value) { .then((void value) {

View File

@ -34,8 +34,7 @@ abstract class BoardPhantomControllerDelegate {
); );
} }
class BoardPhantomController extends OverlapReorderFlexDragTargetDelegate class BoardPhantomController extends OverlapDragTargetDelegate with CrossReorderFlexDragTargetDelegate {
with CrossReorderFlexDragTargetDelegate {
PhantomRecord? phantomRecord; PhantomRecord? phantomRecord;
final BoardPhantomControllerDelegate delegate; final BoardPhantomControllerDelegate delegate;
final columnsState = ColumnPhantomStateController(); final columnsState = ColumnPhantomStateController();
@ -117,8 +116,7 @@ class BoardPhantomController extends OverlapReorderFlexDragTargetDelegate
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
Future.delayed(const Duration(milliseconds: 100), () { Future.delayed(const Duration(milliseconds: 100), () {
Log.debug( Log.debug('[$BoardPhantomController] notify $toColumnId to insert phantom');
'[$BoardPhantomController] notify $toColumnId to insert phantom');
columnsState.notifyDidInsertPhantom(toColumnId); columnsState.notifyDidInsertPhantom(toColumnId);
}); });
}); });
@ -185,7 +183,7 @@ class BoardPhantomController extends OverlapReorderFlexDragTargetDelegate
} }
@override @override
void dragTargetDidDisappear() { void didReturnOriginalDragTarget() {
if (phantomRecord == null) { if (phantomRecord == null) {
return; return;
} }
@ -193,6 +191,19 @@ class BoardPhantomController extends OverlapReorderFlexDragTargetDelegate
_removePhantom(phantomRecord!.toColumnId); _removePhantom(phantomRecord!.toColumnId);
phantomRecord = null; phantomRecord = null;
} }
@override
void didCrossOtherDragTarget(
String reorderFlexId,
FlexDragTargetData dragTargetData,
int dragTargetIndex,
) {
acceptNewDragTargetData(
reorderFlexId,
dragTargetData,
dragTargetIndex,
);
}
} }
/// Use [PhantomRecord] to record where to remove the column item and where to /// Use [PhantomRecord] to record where to remove the column item and where to
@ -221,8 +232,7 @@ class PhantomRecord {
if (fromColumnIndex == index) { if (fromColumnIndex == index) {
return; return;
} }
Log.debug( Log.debug('[$PhantomRecord] Update Column$fromColumnId remove position to $index');
'[$PhantomRecord] Update Column$fromColumnId remove position to $index');
fromColumnIndex = index; fromColumnIndex = index;
} }
@ -231,8 +241,7 @@ class PhantomRecord {
return; return;
} }
Log.debug( Log.debug('[$PhantomRecord] Column$toColumnId update position $toColumnIndex -> $index');
'[$PhantomRecord] Column$toColumnId update position $toColumnIndex -> $index');
toColumnIndex = index; toColumnIndex = index;
} }
@ -245,8 +254,7 @@ class PhantomRecord {
class PhantomColumnItem extends ColumnItem { class PhantomColumnItem extends ColumnItem {
final PassthroughPhantomContext phantomContext; final PassthroughPhantomContext phantomContext;
PhantomColumnItem(PassthroughPhantomContext insertedPhantom) PhantomColumnItem(PassthroughPhantomContext insertedPhantom) : phantomContext = insertedPhantom;
: phantomContext = insertedPhantom;
@override @override
bool get isPhantom => true; bool get isPhantom => true;
@ -256,9 +264,8 @@ class PhantomColumnItem extends ColumnItem {
Size? get feedbackSize => phantomContext.feedbackSize; Size? get feedbackSize => phantomContext.feedbackSize;
Widget get draggingWidget => phantomContext.draggingWidget == null Widget get draggingWidget =>
? const SizedBox() phantomContext.draggingWidget == null ? const SizedBox() : phantomContext.draggingWidget!;
: phantomContext.draggingWidget!;
@override @override
String toString() { String toString() {

View File

@ -97,13 +97,7 @@ class PhantomInsertNotifier extends ChangeNotifier {
} }
class PhantomDeleteNotifier extends ChangeNotifier { class PhantomDeleteNotifier extends ChangeNotifier {
// int deletedIndex = -1;
void remove() { void remove() {
// if (this.deletedIndex != deletedIndex) {
// this.deletedIndex = deletedIndex;
// notifyListeners();
// }
notifyListeners(); notifyListeners();
} }
} }