diff --git a/frontend/app_flowy/packages/flowy_board/lib/src/utils/log.dart b/frontend/app_flowy/packages/flowy_board/lib/src/utils/log.dart index b9f766f961..5d39219f2e 100644 --- a/frontend/app_flowy/packages/flowy_board/lib/src/utils/log.dart +++ b/frontend/app_flowy/packages/flowy_board/lib/src/utils/log.dart @@ -22,7 +22,7 @@ class Log { static void trace(String? message) { if (enableLog) { - // debugPrint('❗️[Trace]=> $message'); + debugPrint('❗️[Trace]=> $message'); } } } diff --git a/frontend/app_flowy/packages/flowy_board/lib/src/widgets/board_data.dart b/frontend/app_flowy/packages/flowy_board/lib/src/widgets/board_data.dart index 13918c1f4e..0e095b1a09 100644 --- a/frontend/app_flowy/packages/flowy_board/lib/src/widgets/board_data.dart +++ b/frontend/app_flowy/packages/flowy_board/lib/src/widgets/board_data.dart @@ -8,6 +8,7 @@ import 'flex/reorder_flex.dart'; import 'package:flutter/material.dart'; import 'phantom/phantom_controller.dart'; +@protected class BoardDataController extends ChangeNotifier with EquatableMixin, BoardPhantomControllerDelegate, ReoderFlextDataSource { final List _columnDatas = []; diff --git a/frontend/app_flowy/packages/flowy_board/lib/src/widgets/flex/reorder_flex.dart b/frontend/app_flowy/packages/flowy_board/lib/src/widgets/flex/reorder_flex.dart index fb861ae3ba..d2dc7583c8 100644 --- a/frontend/app_flowy/packages/flowy_board/lib/src/widgets/flex/reorder_flex.dart +++ b/frontend/app_flowy/packages/flowy_board/lib/src/widgets/flex/reorder_flex.dart @@ -14,7 +14,8 @@ typedef OnDragEnded = void Function(); typedef OnReorder = void Function(int fromIndex, int toIndex); typedef OnDeleted = void Function(int deletedIndex); typedef OnInserted = void Function(int insertedIndex); -typedef OnReveivePassedInPhantom = void Function(FlexDragTargetData dragTargetData, int phantomIndex); +typedef OnReveivePassedInPhantom = void Function( + FlexDragTargetData dragTargetData, int phantomIndex); abstract class ReoderFlextDataSource { /// [identifier] represents the id the [ReorderFlex]. It must be unique. @@ -90,7 +91,8 @@ class ReorderFlex extends StatefulWidget { String get reorderFlexId => dataSource.identifier; } -class ReorderFlexState extends State with ReorderFlexMinxi, TickerProviderStateMixin { +class ReorderFlexState extends State + with ReorderFlexMinxi, TickerProviderStateMixin { /// Controls scrolls and measures scroll progress. late ScrollController _scrollController; @@ -130,7 +132,9 @@ class ReorderFlexState extends State with ReorderFlexMinxi, TickerP _attachedScrollPosition = null; } - _scrollController = widget.scrollController ?? PrimaryScrollController.of(context) ?? ScrollController(); + _scrollController = widget.scrollController ?? + PrimaryScrollController.of(context) ?? + ScrollController(); if (_scrollController.hasClients) { _attachedScrollPosition = Scrollable.of(context)?.position; @@ -252,7 +256,9 @@ class ReorderFlexState extends State with ReorderFlexMinxi, TickerP ]); } else if (childIndex == dragPhantomIndex) { return _buildDraggingContainer( - children: shiftedIndex <= childIndex ? [dragTarget, disappearSpace] : [disappearSpace, dragTarget]); + children: shiftedIndex <= childIndex + ? [dragTarget, disappearSpace] + : [disappearSpace, dragTarget]); } } @@ -273,7 +279,9 @@ class ReorderFlexState extends State with ReorderFlexMinxi, TickerP ]); } else if (childIndex == dragPhantomIndex) { return _buildDraggingContainer( - children: shiftedIndex >= childIndex ? [disappearSpace, dragTarget] : [dragTarget, disappearSpace]); + children: shiftedIndex >= childIndex + ? [disappearSpace, dragTarget] + : [dragTarget, disappearSpace]); } } @@ -299,7 +307,8 @@ class ReorderFlexState extends State with ReorderFlexMinxi, TickerP Widget child, int dragTargetIndex, ) { - final ReoderFlexItem reorderFlexItem = widget.dataSource.items[dragTargetIndex]; + final ReoderFlexItem reorderFlexItem = + widget.dataSource.items[dragTargetIndex]; return ReorderDragTarget( dragTargetData: FlexDragTargetData( draggingIndex: dragTargetIndex, @@ -309,12 +318,14 @@ class ReorderFlexState extends State with ReorderFlexMinxi, TickerP dragTargetId: reorderFlexItem.id, ), onDragStarted: (draggingWidget, draggingIndex, size) { - Log.debug("[DragTarget] Column${widget.dataSource.identifier} start dragging"); + Log.debug( + "[DragTarget] Column${widget.dataSource.identifier} start dragging item at $draggingIndex"); _startDragging(draggingWidget, draggingIndex, size); widget.onDragStarted?.call(draggingIndex); }, onDragEnded: (dragTargetData) { - Log.debug("[DragTarget]: Column${widget.dataSource.identifier} end dragging"); + Log.debug( + "[DragTarget]: Column${widget.dataSource.identifier} end dragging"); setState(() { _onReordered( @@ -411,7 +422,8 @@ class ReorderFlexState extends State with ReorderFlexMinxi, TickerP Log.trace( '[$ReorderDragTarget] ${widget.dataSource.identifier} on will accept, dragIndex:$dragIndex, dragTargetIndex:$dragTargetIndex, count: ${widget.dataSource.items.length}'); - bool willAccept = dragState.dragStartIndex == dragIndex && dragIndex != dragTargetIndex; + bool willAccept = + dragState.dragStartIndex == dragIndex && dragIndex != dragTargetIndex; setState(() { if (willAccept) { int shiftedIndex = dragState.calculateShiftedIndex(dragTargetIndex); @@ -438,7 +450,8 @@ class ReorderFlexState extends State with ReorderFlexMinxi, TickerP } Widget _wrapScrollView({required Widget child}) { - if (widget.scrollController != null && PrimaryScrollController.of(context) == null) { + if (widget.scrollController != null && + PrimaryScrollController.of(context) == null) { return child; } else { return SingleChildScrollView( @@ -492,12 +505,14 @@ class ReorderFlexState extends State with ReorderFlexMinxi, TickerP void _scrollTo(BuildContext context) { if (_scrolling) return; final RenderObject contextObject = context.findRenderObject()!; - final RenderAbstractViewport viewport = RenderAbstractViewport.of(contextObject)!; + final RenderAbstractViewport viewport = + RenderAbstractViewport.of(contextObject)!; // 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 // screen, then it is already on-screen. - final double margin = - widget.direction == Axis.horizontal ? dragState.dropAreaSize.width : dragState.dropAreaSize.height; + final double margin = widget.direction == Axis.horizontal + ? dragState.dropAreaSize.width + : dragState.dropAreaSize.height; if (_scrollController.hasClients) { final double scrollOffset = _scrollController.offset; final double topOffset = max( @@ -508,7 +523,8 @@ class ReorderFlexState extends State with ReorderFlexMinxi, TickerP _scrollController.position.maxScrollExtent, viewport.getOffsetToReveal(contextObject, 1.0).offset + margin, ); - final bool onScreen = scrollOffset <= topOffset && scrollOffset >= bottomOffset; + final bool onScreen = + scrollOffset <= topOffset && scrollOffset >= bottomOffset; // If the context is off screen, then we request a scroll to make it visible. if (!onScreen) { diff --git a/frontend/app_flowy/packages/flowy_board/lib/src/widgets/flex/reorder_mixin.dart b/frontend/app_flowy/packages/flowy_board/lib/src/widgets/flex/reorder_mixin.dart index 76b7d834a4..1d9e764ade 100644 --- a/frontend/app_flowy/packages/flowy_board/lib/src/widgets/flex/reorder_mixin.dart +++ b/frontend/app_flowy/packages/flowy_board/lib/src/widgets/flex/reorder_mixin.dart @@ -6,60 +6,78 @@ mixin ReorderFlexMinxi { @protected Widget makeAppearingWidget( Widget child, - AnimationController entranceController, + AnimationController animationController, Size? draggingFeedbackSize, Axis direction, ) { + final sizeFactor = animationController.withLinearCurve(); if (null == draggingFeedbackSize) { return SizeTransitionWithIntrinsicSize( - sizeFactor: entranceController, + sizeFactor: sizeFactor, axis: direction, child: FadeTransition( - opacity: entranceController, + opacity: sizeFactor, child: child, ), ); } else { var transition = SizeTransition( - sizeFactor: entranceController, + sizeFactor: sizeFactor, axis: direction, - child: FadeTransition(opacity: entranceController, child: child), + child: FadeTransition(opacity: animationController, child: child), ); - BoxConstraints contentSizeConstraints = - BoxConstraints.loose(draggingFeedbackSize); - return ConstrainedBox( - constraints: contentSizeConstraints, child: transition); + BoxConstraints contentSizeConstraints = BoxConstraints.loose(draggingFeedbackSize); + return ConstrainedBox(constraints: contentSizeConstraints, child: transition); } } @protected Widget makeDisappearingWidget( Widget child, - AnimationController phantomController, + AnimationController animationController, Size? draggingFeedbackSize, Axis direction, ) { + final sizeFactor = animationController.withLinearCurve(); if (null == draggingFeedbackSize) { return SizeTransitionWithIntrinsicSize( - sizeFactor: phantomController, + sizeFactor: sizeFactor, axis: direction, child: FadeTransition( - opacity: phantomController, + opacity: sizeFactor, child: child, ), ); } else { var transition = SizeTransition( - sizeFactor: phantomController, + sizeFactor: sizeFactor, axis: direction, - child: FadeTransition(opacity: phantomController, child: child), + child: FadeTransition(opacity: animationController, child: child), ); - BoxConstraints contentSizeConstraints = - BoxConstraints.loose(draggingFeedbackSize); - return ConstrainedBox( - constraints: contentSizeConstraints, child: transition); + BoxConstraints contentSizeConstraints = BoxConstraints.loose(draggingFeedbackSize); + return ConstrainedBox(constraints: contentSizeConstraints, child: transition); } } } + +Animation withCurve(AnimationController animationController, Cubic curve) { + return CurvedAnimation( + parent: animationController, + curve: curve, + ); +} + +extension CurveAnimationController on AnimationController { + Animation withLinearCurve() { + return withCurve(Curves.linear); + } + + Animation withCurve(Curve curve) { + return CurvedAnimation( + parent: this, + curve: curve, + ); + } +}