diff --git a/lib/src/editor/editor_component/service/selection/mobile_selection_service.dart b/lib/src/editor/editor_component/service/selection/mobile_selection_service.dart index ca87377b7..786516e7d 100644 --- a/lib/src/editor/editor_component/service/selection/mobile_selection_service.dart +++ b/lib/src/editor/editor_component/service/selection/mobile_selection_service.dart @@ -19,15 +19,15 @@ StreamController appFlowyEditorOnTapSelectionArea = enum MobileSelectionDragMode { none, - leftSelectionHandler, - rightSelectionHandler, + leftSelectionHandle, + rightSelectionHandle, cursor; } enum MobileSelectionHandlerType { - leftHandler, - rightHandler, - cursorHandler, + leftHandle, + rightHandle, + cursorHandle, } // the value type is MobileSelectionDragMode @@ -165,6 +165,14 @@ class _MobileSelectionServiceWidgetState return const SizedBox.shrink(); } + if (selection.isCollapsed && + [ + MobileSelectionDragMode.leftSelectionHandle, + MobileSelectionDragMode.rightSelectionHandle, + ].contains(dragMode)) { + return const SizedBox.shrink(); + } + selection = selection.normalized; final node = editorState.getNodeAtPath(selection.start.path); @@ -208,10 +216,24 @@ class _MobileSelectionServiceWidgetState return ValueListenableBuilder( valueListenable: selectionNotifierAfterLayout, builder: (context, selection, _) { - if (selection == null || selection.isCollapsed) { + if (selection == null) { + return const SizedBox.shrink(); + } + + if (selection.isCollapsed && + [ + MobileSelectionDragMode.none, + MobileSelectionDragMode.cursor, + ].contains(dragMode)) { return const SizedBox.shrink(); } + final isCollapsedWhenDraggingHandle = selection.isCollapsed && + [ + MobileSelectionDragMode.leftSelectionHandle, + MobileSelectionDragMode.rightSelectionHandle, + ].contains(dragMode); + selection = selection.normalized; final node = editorState.getNodeAtPath( @@ -220,10 +242,20 @@ class _MobileSelectionServiceWidgetState : selection.end.path, ); final selectable = node?.selectable; - final rects = selectable?.getRectsInSelection( - selection, - shiftWithBaseOffset: true, - ); + + // get the cursor rect when the selection is collapsed. + final rects = isCollapsedWhenDraggingHandle + ? [ + selectable?.getCursorRectInPosition( + selection.start, + shiftWithBaseOffset: true, + ) ?? + Rect.zero, + ] + : selectable?.getRectsInSelection( + selection, + shiftWithBaseOffset: true, + ); if (node == null || rects == null || rects.isEmpty) { return const SizedBox.shrink(); @@ -234,7 +266,9 @@ class _MobileSelectionServiceWidgetState layerLink: node.layerLink, rect: handleType == HandleType.left ? rects.first : rects.last, handleType: handleType, - handleColor: editorStyle.dragHandleColor, + handleColor: isCollapsedWhenDraggingHandle + ? Colors.transparent + : editorStyle.dragHandleColor, handleWidth: editorStyle.mobileDragHandleWidth, handleBallWidth: editorStyle.mobileDragHandleBallSize.width, enableHapticFeedbackOnAndroid: @@ -276,6 +310,7 @@ class _MobileSelectionServiceWidgetState void clearSelection() { currentSelectedNodes = []; currentSelection.value = null; + _lastPanOffset.value = null; _clearSelection(); } @@ -470,12 +505,12 @@ class _MobileSelectionServiceWidgetState Selection? newSelection; if (end != null) { - if (dragMode == MobileSelectionDragMode.leftSelectionHandler) { + if (dragMode == MobileSelectionDragMode.leftSelectionHandle) { newSelection = Selection( start: _panStartSelection!.normalized.end, end: end, ).normalized; - } else if (dragMode == MobileSelectionDragMode.rightSelectionHandler) { + } else if (dragMode == MobileSelectionDragMode.rightSelectionHandle) { newSelection = Selection( start: _panStartSelection!.normalized.start, end: end, diff --git a/lib/src/editor/toolbar/mobile/mobile_floating_toolbar/mobile_floating_toolbar.dart b/lib/src/editor/toolbar/mobile/mobile_floating_toolbar/mobile_floating_toolbar.dart index def011795..5d83dc3b9 100644 --- a/lib/src/editor/toolbar/mobile/mobile_floating_toolbar/mobile_floating_toolbar.dart +++ b/lib/src/editor/toolbar/mobile/mobile_floating_toolbar/mobile_floating_toolbar.dart @@ -122,8 +122,8 @@ class _MobileFloatingToolbarState extends State _clear(); final dragMode = editorState.selectionExtraInfo?[selectionDragModeKey]; if ([ - MobileSelectionDragMode.leftSelectionHandler, - MobileSelectionDragMode.rightSelectionHandler, + MobileSelectionDragMode.leftSelectionHandle, + MobileSelectionDragMode.rightSelectionHandle, ].contains(dragMode)) { return; } diff --git a/lib/src/render/selection/mobile_basic_handle.dart b/lib/src/render/selection/mobile_basic_handle.dart index f412b0423..7d14e8f36 100644 --- a/lib/src/render/selection/mobile_basic_handle.dart +++ b/lib/src/render/selection/mobile_basic_handle.dart @@ -23,9 +23,9 @@ enum HandleType { case HandleType.none: throw UnsupportedError('Unsupported handle type'); case HandleType.left: - return MobileSelectionDragMode.leftSelectionHandler; + return MobileSelectionDragMode.leftSelectionHandle; case HandleType.right: - return MobileSelectionDragMode.rightSelectionHandler; + return MobileSelectionDragMode.rightSelectionHandle; case HandleType.collapsed: return MobileSelectionDragMode.cursor; } @@ -207,19 +207,25 @@ class _IOSDragHandle extends _IDragHandle { final editorState = context.read(); final ballWidth = handleBallWidth; + double offset = 0.0; + if (handleType == HandleType.left) { + offset = ballWidth; + } else if (handleType == HandleType.right) { + offset = -ballWidth; + } child = GestureDetector( behavior: HitTestBehavior.opaque, dragStartBehavior: DragStartBehavior.down, onPanStart: (details) { editorState.service.selectionService.onPanStart( - details.translate(0, -ballWidth), + details.translate(0, offset), handleType.dragMode, ); }, onPanUpdate: (details) { editorState.service.selectionService.onPanUpdate( - details.translate(0, -ballWidth), + details.translate(0, offset), handleType.dragMode, ); },