Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable debug paint size for mobile drag handle #1007

Merged
merged 3 commits into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion example/lib/pages/mobile_editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class _MobileEditorState extends State<MobileEditor> {

editorStyle = _buildMobileEditorStyle();
blockComponentBuilders = _buildBlockComponentBuilders();

editorState.debugInfo.debugPaintSizeEnabled = true;
}

@override
Expand Down Expand Up @@ -125,7 +127,9 @@ class _MobileEditorState extends State<MobileEditor> {
),
padding: const EdgeInsets.symmetric(horizontal: 24.0),
magnifierSize: const Size(144, 96),
mobileDragHandleBallSize: const Size(12, 12),
mobileDragHandleBallSize: const Size.square(8),
mobileDragHandleLeftExtend: 12.0,
mobileDragHandleWidthExtend: 24.0,
);
}

Expand Down
6 changes: 6 additions & 0 deletions lib/src/core/transform/transaction.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ class Transaction {
/// The before selection is to be recovered if needed.
Selection? beforeSelection;

/// The custom selection type is to be applied.
SelectionType? customSelectionType;

/// The custom selection reason is to be applied.
SelectionUpdateReason? reason;

Map? selectionExtraInfo;

// mark needs to be composed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,15 @@
// for the another keyboards (e.g. system keyboard), they will trigger the
// `onFloatingCursor` event instead.
AppFlowyEditorLog.input.debug('[Android] onNonTextUpdate: $nonTextUpdate');
if (selection != null) {
if (selection != null && selection != editorState.selection) {

Check warning on line 62 in lib/src/editor/editor_component/service/ime/delta_input_on_non_text_update_impl.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/editor_component/service/ime/delta_input_on_non_text_update_impl.dart#L62

Added line #L62 was not covered by tests
editorState.updateSelectionWithReason(
Selection.collapsed(
Position(
path: selection.start.path,
offset: nonTextUpdate.selection.start,
),
),
reason: SelectionUpdateReason.uiEvent,
);
}
} else if (PlatformExtension.isIOS) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@
..setCaretRect(rect);
}

@override

Check warning on line 95 in lib/src/editor/editor_component/service/ime/delta_input_service.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/editor_component/service/ime/delta_input_service.dart#L95

Added line #L95 was not covered by tests
void clearComposingTextRange() {
composingTextRange = TextRange.empty;

Check warning on line 97 in lib/src/editor/editor_component/service/ime/delta_input_service.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/editor_component/service/ime/delta_input_service.dart#L97

Added line #L97 was not covered by tests
}

@override
void connectionClosed() {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@
..setComposingRect(rect.translate(0, rect.height));
}

@override

Check warning on line 147 in lib/src/editor/editor_component/service/ime/non_delta_input_service.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/editor_component/service/ime/non_delta_input_service.dart#L147

Added line #L147 was not covered by tests
void clearComposingTextRange() {
composingTextRange = TextRange.empty;

Check warning on line 149 in lib/src/editor/editor_component/service/ime/non_delta_input_service.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/editor_component/service/ime/non_delta_input_service.dart#L149

Added line #L149 was not covered by tests
}

@override
void connectionClosed() {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ abstract class TextInputService {
TextRange? get composingTextRange;
bool get attached;

void clearComposingTextRange();

void updateCaretPosition(Size size, Matrix4 transform, Rect rect);

/// Updates the [TextEditingValue] of the text currently being edited.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:appflowy_editor/src/editor/editor_component/service/ime/delta_input_on_floating_cursor_update.dart';
import 'package:appflowy_editor/src/editor/util/platform_extension.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
Expand Down Expand Up @@ -216,6 +217,9 @@

void _attachTextInputService(Selection selection) {
final textEditingValue = _getCurrentTextEditingValue(selection);
AppFlowyEditorLog.editor.debug(
'keyboard service - attach text input service: $textEditingValue',
);
if (textEditingValue != null) {
textInputService.attach(
textEditingValue,
Expand Down Expand Up @@ -244,6 +248,16 @@
.getNodesInSelection(selection)
.where((element) => element.delta != null);

// if the selection is inline and the selection is updated by ui event,
// we should clear the composing range on Android.
final shouldClearComposingRange =
editorState.selectionType == SelectionType.inline &&
editorState.selectionUpdateReason == SelectionUpdateReason.uiEvent;

if (PlatformExtension.isAndroid && shouldClearComposingRange) {
textInputService.clearComposingTextRange();

Check warning on line 258 in lib/src/editor/editor_component/service/keyboard_service_widget.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/editor_component/service/keyboard_service_widget.dart#L258

Added line #L258 was not covered by tests
}

// Get the composing text range.
final composingTextRange =
textInputService.composingTextRange ?? TextRange.empty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@
listen: false,
);

bool isCollapsedHandleVisible = false;

Timer? collapsedHandleTimer;

@override
void initState() {
super.initState();
Expand All @@ -113,6 +117,7 @@
WidgetsBinding.instance.removeObserver(this);
selectionNotifierAfterLayout.dispose();
editorState.selectionNotifier.removeListener(_updateSelection);
collapsedHandleTimer?.cancel();

super.dispose();
}
Expand Down Expand Up @@ -178,13 +183,15 @@
valueListenable: selectionNotifierAfterLayout,
builder: (context, selection, _) {
if (selection == null || !selection.isCollapsed) {
isCollapsedHandleVisible = false;
return const SizedBox.shrink();
}

// on iOS, the drag handle should be updated when typing text.
// on Android, the drag handle should be updated when typing text.
if (PlatformExtension.isAndroid &&
editorState.selectionUpdateReason !=
SelectionUpdateReason.uiEvent) {
isCollapsedHandleVisible = false;

Check warning on line 194 in lib/src/editor/editor_component/service/selection/mobile_selection_service.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/editor_component/service/selection/mobile_selection_service.dart#L194

Added line #L194 was not covered by tests
return const SizedBox.shrink();
}

Expand All @@ -193,6 +200,7 @@
MobileSelectionDragMode.leftSelectionHandle,
MobileSelectionDragMode.rightSelectionHandle,
].contains(dragMode)) {
isCollapsedHandleVisible = false;

Check warning on line 203 in lib/src/editor/editor_component/service/selection/mobile_selection_service.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/editor_component/service/selection/mobile_selection_service.dart#L203

Added line #L203 was not covered by tests
return const SizedBox.shrink();
}

Expand All @@ -206,9 +214,14 @@
);

if (node == null || rect == null) {
isCollapsedHandleVisible = false;

Check warning on line 217 in lib/src/editor/editor_component/service/selection/mobile_selection_service.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/editor_component/service/selection/mobile_selection_service.dart#L217

Added line #L217 was not covered by tests
return const SizedBox.shrink();
}

isCollapsedHandleVisible = true;

Check warning on line 221 in lib/src/editor/editor_component/service/selection/mobile_selection_service.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/editor_component/service/selection/mobile_selection_service.dart#L221

Added line #L221 was not covered by tests

_clearCollapsedHandleOnAndroid();

Check warning on line 223 in lib/src/editor/editor_component/service/selection/mobile_selection_service.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/editor_component/service/selection/mobile_selection_service.dart#L223

Added line #L223 was not covered by tests

final editorStyle = editorState.editorStyle;
return MobileCollapsedHandle(
layerLink: node.layerLink,
Expand All @@ -218,6 +231,14 @@
handleBallWidth: editorStyle.mobileDragHandleBallSize.width,
enableHapticFeedbackOnAndroid:
editorStyle.enableHapticFeedbackOnAndroid,
onDragging: (isDragging) {

Check warning on line 234 in lib/src/editor/editor_component/service/selection/mobile_selection_service.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/editor_component/service/selection/mobile_selection_service.dart#L234

Added line #L234 was not covered by tests
if (isDragging) {
collapsedHandleTimer?.cancel();
collapsedHandleTimer = null;

Check warning on line 237 in lib/src/editor/editor_component/service/selection/mobile_selection_service.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/editor_component/service/selection/mobile_selection_service.dart#L236-L237

Added lines #L236 - L237 were not covered by tests
} else {
_clearCollapsedHandleOnAndroid();

Check warning on line 239 in lib/src/editor/editor_component/service/selection/mobile_selection_service.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/editor_component/service/selection/mobile_selection_service.dart#L239

Added line #L239 was not covered by tests
}
},
);
},
);
Expand Down Expand Up @@ -301,6 +322,25 @@
);
}

// The collapsed handle will be dismissed when no user interaction is detected.
void _clearCollapsedHandleOnAndroid() {
if (!PlatformExtension.isAndroid) {

Check warning on line 327 in lib/src/editor/editor_component/service/selection/mobile_selection_service.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/editor_component/service/selection/mobile_selection_service.dart#L326-L327

Added lines #L326 - L327 were not covered by tests
return;
}
collapsedHandleTimer?.cancel();
collapsedHandleTimer = Timer(
editorState.editorStyle.autoDismissCollapsedHandleDuration,
() {
if (isCollapsedHandleVisible) {
editorState.updateSelectionWithReason(
editorState.selection,

Check warning on line 336 in lib/src/editor/editor_component/service/selection/mobile_selection_service.dart

View check run for this annotation

Codecov / codecov/patch

lib/src/editor/editor_component/service/selection/mobile_selection_service.dart#L330-L336

Added lines #L330 - L336 were not covered by tests
reason: SelectionUpdateReason.transaction,
);
}
},
);
}

@override
void updateSelection(Selection? selection) {
if (currentSelection.value == selection) {
Expand Down
51 changes: 50 additions & 1 deletion lib/src/editor/editor_component/style/editor_style.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ class EditorStyle {
this.enableHapticFeedbackOnAndroid = true,
this.textScaleFactor = 1.0,
this.maxWidth,
this.mobileDragHandleTopExtend,
this.mobileDragHandleWidthExtend,
this.mobileDragHandleLeftExtend,
this.mobileDragHandleHeightExtend,
this.autoDismissCollapsedHandleDuration = const Duration(seconds: 3),
});

// The padding of the editor.
Expand Down Expand Up @@ -69,6 +74,25 @@ class EditorStyle {
// Only works on mobile.
final Size mobileDragHandleBallSize;

/// The extend of the mobile drag handle.
///
/// By default, the hit test area of drag handle is the ball size.
/// If you want to extend the hit test area, you can set this value.
///
/// For example, if you set this value to 10, the hit test area of drag handle
/// will be the ball size + 10 * 2.
final double? mobileDragHandleTopExtend;
final double? mobileDragHandleLeftExtend;
final double? mobileDragHandleWidthExtend;
final double? mobileDragHandleHeightExtend;

/// The auto-dismiss time of the collapsed handle.
///
/// The collapsed handle will be dismissed when no user interaction is detected.
///
/// Only works on Android.
final Duration autoDismissCollapsedHandleDuration;

final double mobileDragHandleWidth;

// only works on android
Expand Down Expand Up @@ -101,7 +125,12 @@ class EditorStyle {
mobileDragHandleBallSize = Size.zero,
mobileDragHandleWidth = 0.0,
enableHapticFeedbackOnAndroid = false,
dragHandleColor = Colors.transparent;
dragHandleColor = Colors.transparent,
mobileDragHandleTopExtend = null,
mobileDragHandleWidthExtend = null,
mobileDragHandleLeftExtend = null,
mobileDragHandleHeightExtend = null,
autoDismissCollapsedHandleDuration = const Duration(seconds: 0);

const EditorStyle.mobile({
EdgeInsets? padding,
Expand All @@ -118,6 +147,11 @@ class EditorStyle {
this.enableHapticFeedbackOnAndroid = true,
this.textScaleFactor = 1.0,
this.maxWidth,
this.mobileDragHandleTopExtend,
this.mobileDragHandleWidthExtend,
this.mobileDragHandleLeftExtend,
this.mobileDragHandleHeightExtend,
this.autoDismissCollapsedHandleDuration = const Duration(seconds: 3),
}) : padding = padding ?? const EdgeInsets.symmetric(horizontal: 20),
cursorColor = cursorColor ?? const Color(0xFF00BCF0),
dragHandleColor = dragHandleColor ?? const Color(0xFF00BCF0),
Expand Down Expand Up @@ -145,6 +179,11 @@ class EditorStyle {
double? cursorWidth,
double? textScaleFactor,
double? maxWidth,
double? mobileDragHandleTopExtend,
double? mobileDragHandleWidthExtend,
double? mobileDragHandleLeftExtend,
double? mobileDragHandleHeightExtend,
Duration? autoDismissCollapsedHandleDuration,
}) {
return EditorStyle(
padding: padding ?? this.padding,
Expand All @@ -165,6 +204,16 @@ class EditorStyle {
cursorWidth: cursorWidth ?? this.cursorWidth,
textScaleFactor: textScaleFactor ?? this.textScaleFactor,
maxWidth: maxWidth ?? this.maxWidth,
mobileDragHandleTopExtend:
mobileDragHandleTopExtend ?? this.mobileDragHandleTopExtend,
mobileDragHandleWidthExtend:
mobileDragHandleWidthExtend ?? this.mobileDragHandleWidthExtend,
mobileDragHandleLeftExtend:
mobileDragHandleLeftExtend ?? this.mobileDragHandleLeftExtend,
mobileDragHandleHeightExtend:
mobileDragHandleHeightExtend ?? this.mobileDragHandleHeightExtend,
autoDismissCollapsedHandleDuration: autoDismissCollapsedHandleDuration ??
this.autoDismissCollapsedHandleDuration,
);
}
}
20 changes: 19 additions & 1 deletion lib/src/editor_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ typedef EditorTransactionValue = (
ApplyOptions options,
);

class EditorStateDebugInfo {
EditorStateDebugInfo({
this.debugPaintSizeEnabled = false,
});

/// Enable the debug paint size for selection handle.
///
/// It only available on mobile.
bool debugPaintSizeEnabled;
}

/// the type of this value is bool.
///
/// set true to this key to prevent attaching the text service when selection is changed.
Expand Down Expand Up @@ -166,6 +177,11 @@ class EditorState {
service.rendererService = value;
}

/// Customize the debug info for the editor state.
///
/// Refer to [EditorStateDebugInfo] for more details.
EditorStateDebugInfo debugInfo = EditorStateDebugInfo();

/// store the auto scroller instance in here temporarily.
AutoScroller? autoScroller;
ScrollableState? scrollableState;
Expand Down Expand Up @@ -360,7 +376,9 @@ class EditorState {
_recordRedoOrUndo(options, transaction, skipHistoryDebounce);

if (withUpdateSelection) {
_selectionUpdateReason = SelectionUpdateReason.transaction;
_selectionUpdateReason =
transaction.reason ?? SelectionUpdateReason.transaction;
_selectionType = transaction.customSelectionType;
if (transaction.selectionExtraInfo != null) {
selectionExtraInfo = transaction.selectionExtraInfo;
}
Expand Down
Loading
Loading