feat: add interceptor into selection service to custom the drag target node (#1044)

This commit is contained in:
Lucas 2025-02-26 14:20:19 +08:00 • committed by GitHub
commit 400083fde6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 70 additions and 16 deletions

View file

@ -437,12 +437,21 @@ class _DesktopSelectionServiceWidgetState
void renderDropTargetForOffset(
Offset offset, {
DragAreaBuilder? builder,
DragTargetNodeInterceptor? interceptor,
}) {
removeDropTarget();
final node = getNodeInOffset(offset);
final selectable = node?.selectable;
if (node == null || selectable == null) {
Node? node = getNodeInOffset(offset);
if (node == null) {
return;
}
if (interceptor != null) {
node = interceptor(context, node);
}
final selectable = node.selectable;
if (selectable == null) {
return;
}
@ -461,7 +470,7 @@ class _DesktopSelectionServiceWidgetState
_dropTargetEntry = OverlayEntry(
builder: (context) {
if (builder != null) {
if (builder != null && node != null) {
return builder(
context,
DragAreaBuilderData(
@ -507,9 +516,21 @@ class _DesktopSelectionServiceWidgetState
}
@override
DropTargetRenderData? getDropTargetRenderData(Offset offset) {
final node = getNodeInOffset(offset);
final selectable = node?.selectable;
DropTargetRenderData? getDropTargetRenderData(
Offset offset, {
DragTargetNodeInterceptor? interceptor,
}) {
Node? node = getNodeInOffset(offset);
if (node == null) {
return null;
}
if (interceptor != null) {
node = interceptor(context, node);
}
final selectable = node.selectable;
if (selectable == null) {
return null;
}
@ -527,10 +548,10 @@ class _DesktopSelectionServiceWidgetState
final isCloserToStart = topDistance < bottomDistance;
final dropPath = isCloserToStart ? node?.path : node?.path.next;
final dropPath = isCloserToStart ? node.path : node.path.next;
return DropTargetRenderData(
dropPath: dropPath ?? node?.path,
dropPath: dropPath,
cursorNode: node,
);
}

View file

@ -881,10 +881,18 @@ class _MobileSelectionServiceWidgetState
}
@override
void renderDropTargetForOffset(Offset offset, {DragAreaBuilder? builder}) {
void renderDropTargetForOffset(
Offset offset, {
DragAreaBuilder? builder,
DragTargetNodeInterceptor? interceptor,
}) {
// Do nothing on mobile
}
@override
DropTargetRenderData? getDropTargetRenderData(Offset offset) => null;
DropTargetRenderData? getDropTargetRenderData(
Offset offset, {
DragTargetNodeInterceptor? interceptor,
}) =>
null;
}

View file

@ -19,6 +19,11 @@ typedef DragAreaBuilder = Widget Function(
DragAreaBuilderData data,
);
typedef DragTargetNodeInterceptor = Node Function(
BuildContext context,
Node node,
);
/// [AppFlowySelectionService] is responsible for processing
/// the [Selection] changes and updates.
///
@ -105,9 +110,12 @@ abstract class AppFlowySelectionService {
///
/// If [builder] is provided, the line will be drawn by [builder].
/// Otherwise, the line will be drawn by default [DropTargetStyle].
///
/// If [interceptor] is provided, the node will be intercepted by [interceptor].
void renderDropTargetForOffset(
Offset offset, {
DragAreaBuilder? builder,
DragTargetNodeInterceptor? interceptor,
});
/// Removes the horizontal line drawn by [renderDropTargetForOffset].
@ -116,7 +124,10 @@ abstract class AppFlowySelectionService {
/// Returns the [DropTargetRenderData] for the [offset].
///
DropTargetRenderData? getDropTargetRenderData(Offset offset);
DropTargetRenderData? getDropTargetRenderData(
Offset offset, {
DragTargetNodeInterceptor? interceptor,
});
}
class SelectionGestureInterceptor {

View file

@ -124,10 +124,24 @@ class _SelectionServiceWidgetState extends State<SelectionServiceWidget>
void removeDropTarget() => forward.removeDropTarget();
@override
void renderDropTargetForOffset(Offset offset, {DragAreaBuilder? builder}) =>
forward.renderDropTargetForOffset(offset, builder: builder);
void renderDropTargetForOffset(
Offset offset, {
DragAreaBuilder? builder,
DragTargetNodeInterceptor? interceptor,
}) =>
forward.renderDropTargetForOffset(
offset,
builder: builder,
interceptor: interceptor,
);
@override
DropTargetRenderData? getDropTargetRenderData(Offset offset) =>
forward.getDropTargetRenderData(offset);
DropTargetRenderData? getDropTargetRenderData(
Offset offset, {
DragTargetNodeInterceptor? interceptor,
}) =>
forward.getDropTargetRenderData(
offset,
interceptor: interceptor,
);
}