diff --git a/lib/src/editor/editor_component/service/selection/desktop_selection_service.dart b/lib/src/editor/editor_component/service/selection/desktop_selection_service.dart index 2bcab0cba..30bb40154 100644 --- a/lib/src/editor/editor_component/service/selection/desktop_selection_service.dart +++ b/lib/src/editor/editor_component/service/selection/desktop_selection_service.dart @@ -1,11 +1,13 @@ +import 'package:flutter/material.dart' hide Overlay, OverlayEntry; +import 'package:flutter/services.dart'; + +import 'package:provider/provider.dart'; + import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor/src/editor/editor_component/service/selection/mobile_selection_service.dart'; import 'package:appflowy_editor/src/editor/editor_component/service/selection/shared.dart'; import 'package:appflowy_editor/src/flutter/overlay.dart'; import 'package:appflowy_editor/src/service/selection/selection_gesture.dart'; -import 'package:flutter/material.dart' hide Overlay, OverlayEntry; -import 'package:flutter/services.dart'; -import 'package:provider/provider.dart'; class DesktopSelectionServiceWidget extends StatefulWidget { const DesktopSelectionServiceWidget({ @@ -235,6 +237,14 @@ class _DesktopSelectionServiceWidgetState } void _onDoubleTapDown(TapDownDetails details) { + final canDoubleTap = _interceptors.every( + (interceptor) => interceptor.canDoubleTap?.call(details) ?? true, + ); + + if (!canDoubleTap) { + return updateSelection(null); + } + final offset = details.globalPosition; final node = getNodeInOffset(offset); final selection = node?.selectable?.getWordBoundaryInOffset(offset); @@ -277,6 +287,13 @@ class _DesktopSelectionServiceWidgetState void _onPanStart(DragStartDetails details) { clearSelection(); + final canPanStart = _interceptors + .every((interceptor) => interceptor.canPanStart?.call(details) ?? true); + + if (!canPanStart) { + return; + } + _panStartOffset = details.globalPosition.translate(-3.0, 0); _panStartScrollDy = editorState.service.scrollService?.dy; @@ -286,6 +303,14 @@ class _DesktopSelectionServiceWidgetState } void _onPanUpdate(DragUpdateDetails details) { + final canPanUpdate = _interceptors.every( + (interceptor) => interceptor.canPanUpdate?.call(details) ?? true, + ); + + if (!canPanUpdate) { + return; + } + if (_panStartOffset == null || _panStartScrollDy == null || _panStartPosition == null) { @@ -316,6 +341,13 @@ class _DesktopSelectionServiceWidgetState } void _onPanEnd(DragEndDetails details) { + final canPanEnd = _interceptors + .every((interceptor) => interceptor.canPanEnd?.call(details) ?? true); + + if (!canPanEnd) { + return; + } + _panStartPosition = null; editorState.service.scrollService?.stopAutoScroll(); diff --git a/lib/src/editor/editor_component/service/selection_service.dart b/lib/src/editor/editor_component/service/selection_service.dart index fa42d6080..0b7cc8a84 100644 --- a/lib/src/editor/editor_component/service/selection_service.dart +++ b/lib/src/editor/editor_component/service/selection_service.dart @@ -1,8 +1,9 @@ +import 'package:flutter/material.dart' hide Overlay, OverlayEntry; + import 'package:appflowy_editor/src/core/document/node.dart'; import 'package:appflowy_editor/src/core/location/position.dart'; import 'package:appflowy_editor/src/core/location/selection.dart'; import 'package:appflowy_editor/src/editor/editor_component/service/selection/mobile_selection_service.dart'; -import 'package:flutter/material.dart' hide Overlay, OverlayEntry; /// [AppFlowySelectionService] is responsible for processing /// the [Selection] changes and updates. @@ -87,9 +88,17 @@ class SelectionGestureInterceptor { SelectionGestureInterceptor({ required this.key, this.canTap, + this.canDoubleTap, + this.canPanStart, + this.canPanUpdate, + this.canPanEnd, }); final String key; bool Function(TapDownDetails details)? canTap; + bool Function(TapDownDetails details)? canDoubleTap; + bool Function(DragStartDetails details)? canPanStart; + bool Function(DragUpdateDetails details)? canPanUpdate; + bool Function(DragEndDetails details)? canPanEnd; } diff --git a/test/new/service/shortcuts/command_shortcut_events/copy_paste_handler_test.dart b/test/new/service/shortcuts/command_shortcut_events/copy_paste_handler_test.dart index 228d3b13f..d4dd3440e 100644 --- a/test/new/service/shortcuts/command_shortcut_events/copy_paste_handler_test.dart +++ b/test/new/service/shortcuts/command_shortcut_events/copy_paste_handler_test.dart @@ -1,9 +1,11 @@ import 'dart:io'; -import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:flutter/services.dart'; + import 'package:flutter_test/flutter_test.dart'; +import 'package:appflowy_editor/appflowy_editor.dart'; + import '../../../../infra/clipboard_test.dart'; import '../../../infra/testable_editor.dart'; @@ -40,12 +42,12 @@ void main() async { (tester) async { await _testHandleCopy(tester, Document.fromJson(data)); }); - testWidgets( - 'Presses Command + A in nested document and copy text nestednode', - (tester) async { - // TODO: fix this test - // await _testNestedNodeCopyPaste(tester, Document.fromJson(exampledoc)); - }); + // TODO: fix this test + // testWidgets( + // 'Presses Command + A in nested document and copy text nestednode', + // (tester) async { + // await _testNestedNodeCopyPaste(tester, Document.fromJson(exampledoc)); + // }); testWidgets('update selection and execute cut command', (tester) async { await _testCutHandle(tester, Document.fromJson(cutData)); diff --git a/test/new/service/shortcuts/command_shortcut_events/indent_command_test.dart b/test/new/service/shortcuts/command_shortcut_events/indent_command_test.dart index 96bd404bd..b99db6682 100644 --- a/test/new/service/shortcuts/command_shortcut_events/indent_command_test.dart +++ b/test/new/service/shortcuts/command_shortcut_events/indent_command_test.dart @@ -1,7 +1,9 @@ -import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:flutter/services.dart'; + import 'package:flutter_test/flutter_test.dart'; +import 'package:appflowy_editor/appflowy_editor.dart'; + import '../../../infra/testable_editor.dart'; const _padding = 24.0; @@ -103,8 +105,8 @@ void main() async { }); // TODO(.): The purpose of this test is to catch addPostFrameCallback from - // calculateTextDirection but it doesn't catch it. Commenting the callback - // out doesn't make this test fail. + // calculateTextDirection but it doesn't catch it. Commenting the callback + // out doesn't make this test fail. testWidgets( "indent AUTO line under AUTO line changing the second line calculated direction", (tester) async {