Skip to content

Commit

Permalink
Merge branch 'main' into feat-zhiya
Browse files Browse the repository at this point in the history
* main:
  fix: floating toolbar position error (AppFlowy-IO#598)
  fix: selection menu positioning on right half of editor (AppFlowy-IO#600)
  feat: show magnifier when dragging the handlers (AppFlowy-IO#601)
  fix: editor cannot scroll when editable is false (AppFlowy-IO#599)
  • Loading branch information
q200892907 committed Nov 23, 2023
2 parents 812a46a + af9f97e commit 1ea2a09
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 23 deletions.
1 change: 1 addition & 0 deletions example/lib/pages/mobile_editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class _MobileEditorState extends State<MobileEditor> {
editorState: editorState,
editorScrollController: editorScrollController,
blockComponentBuilders: blockComponentBuilders,
showMagnifier: true,
// showcase 3: customize the header and footer.
header: Padding(
padding: const EdgeInsets.only(bottom: 10.0),
Expand Down
38 changes: 20 additions & 18 deletions lib/src/editor/editor_component/entry/page_block_component.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,27 @@ class PageBlockComponent extends BlockComponentStatelessWidget {
if (scrollController == null ||
scrollController.shrinkWrap ||
!editorState.editable) {
return Builder(
builder: (context) {
final scroller = Scrollable.maybeOf(context);
if (scroller != null) {
editorState.updateAutoScroller(scroller);
}
return Column(
children: [
if (header != null) header!,
...items.map(
(e) => Padding(
padding: editorState.editorStyle.padding,
child: editorState.renderer.build(context, e),
return SingleChildScrollView(
child: Builder(
builder: (context) {
final scroller = Scrollable.maybeOf(context);
if (scroller != null) {
editorState.updateAutoScroller(scroller);
}
return Column(
children: [
if (header != null) header!,
...items.map(
(e) => Padding(
padding: editorState.editorStyle.padding,
child: editorState.renderer.build(context, e),
),
),
),
if (footer != null) footer!,
],
);
},
if (footer != null) footer!,
],
);
},
),
);
} else {
int extentCount = 0;
Expand Down
7 changes: 7 additions & 0 deletions lib/src/editor/editor_component/service/editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class AppFlowyEditor extends StatefulWidget {
this.autoFocus = false,
this.focusedSelection,
this.shrinkWrap = false,
this.showMagnifier = true,
this.editorScrollController,
this.editorStyle = const EditorStyle.desktop(),
this.header,
Expand Down Expand Up @@ -151,6 +152,11 @@ class AppFlowyEditor extends StatefulWidget {
/// Notes: Must provide a scrollController when shrinkWrap is true.
final bool shrinkWrap;

/// Show the magnifier or not.
///
/// only works on iOS or Android.
final bool showMagnifier;

@override
State<AppFlowyEditor> createState() => _AppFlowyEditorState();
}
Expand Down Expand Up @@ -247,6 +253,7 @@ class _AppFlowyEditorState extends State<AppFlowyEditor> {
key: editorState.service.selectionServiceKey,
cursorColor: widget.editorStyle.cursorColor,
selectionColor: widget.editorStyle.selectionColor,
showMagnifier: widget.showMagnifier,
contextMenuItems: widget.contextMenuItems,
child: KeyboardServiceWidget(
key: editorState.service.keyboardServiceKey,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'package:flutter/material.dart';

class MobileMagnifier extends StatelessWidget {
const MobileMagnifier({
super.key,
required this.size,
required this.offset,
});

final Size size;
final Offset offset;

@override
Widget build(BuildContext context) {
return Positioned.fromRect(
rect: Rect.fromCenter(
center: offset.translate(0, -size.height),
width: size.width,
height: size.height,
),
child: IgnorePointer(
child: Magnifier(
size: size,
),
),
);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:appflowy_editor/src/editor/editor_component/service/selection/mobile_magnifiter.dart';
import 'package:appflowy_editor/src/flutter/overlay.dart';
import 'package:appflowy_editor/src/render/selection/mobile_selection_widget.dart';
import 'package:appflowy_editor/src/service/selection/mobile_selection_gesture.dart';
Expand All @@ -23,13 +24,19 @@ class MobileSelectionServiceWidget extends StatefulWidget {
super.key,
this.cursorColor = const Color(0xFF00BCF0),
this.selectionColor = const Color.fromARGB(53, 111, 201, 231),
this.showMagnifier = true,
required this.child,
});

final Widget child;
final Color cursorColor;
final Color selectionColor;

/// Show the magnifier or not.
///
/// only works on iOS or Android.
final bool showMagnifier;

@override
State<MobileSelectionServiceWidget> createState() =>
_MobileSelectionServiceWidgetState();
Expand All @@ -51,6 +58,7 @@ class _MobileSelectionServiceWidgetState
List<Node> currentSelectedNodes = [];

final List<SelectionGestureInterceptor> _interceptors = [];
final ValueNotifier<Offset?> _lastPanOffset = ValueNotifier(null);

/// Pan
Offset? _panStartOffset;
Expand Down Expand Up @@ -90,7 +98,29 @@ class _MobileSelectionServiceWidgetState
onTapUp: _onTapUp,
onDoubleTapUp: _onDoubleTapUp,
onTripleTapUp: _onTripleTapUp,
child: widget.child,
child: Stack(
children: [
widget.child,
if (widget.showMagnifier) _buildMagnifier(),
],
),
);
}

Widget _buildMagnifier() {
return ValueListenableBuilder(
valueListenable: _lastPanOffset,
builder: (_, offset, __) {
if (offset == null) {
return const SizedBox.shrink();
}
final renderBox = context.findRenderObject() as RenderBox;
final local = renderBox.globalToLocal(offset);
return MobileMagnifier(
size: const Size(72, 48),
offset: local,
);
},
);
}

Expand Down Expand Up @@ -337,11 +367,14 @@ class _MobileSelectionServiceWidgetState
Selection.collapsed(end),
);
}

_lastPanOffset.value = panEndOffset;
}
}

void _onPanEnd(DragEndDetails details) {
// do nothing
_lastPanOffset.value = null;
}

void _updateSelectionAreas(Selection selection) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class SelectionServiceWidget extends StatefulWidget {
super.key,
this.cursorColor = const Color(0xFF00BCF0),
this.selectionColor = const Color.fromARGB(53, 111, 201, 231),
this.showMagnifier = true,
required this.contextMenuItems,
required this.child,
});
Expand All @@ -17,6 +18,11 @@ class SelectionServiceWidget extends StatefulWidget {
final Color selectionColor;
final List<List<ContextMenuItem>> contextMenuItems;

/// Show the magnifier or not.
///
/// only works on iOS or Android.
final bool showMagnifier;

@override
State<SelectionServiceWidget> createState() => _SelectionServiceWidgetState();
}
Expand Down Expand Up @@ -46,6 +52,7 @@ class _SelectionServiceWidgetState extends State<SelectionServiceWidget>
key: forwardKey,
cursorColor: widget.cursorColor,
selectionColor: widget.selectionColor,
showMagnifier: widget.showMagnifier,
child: widget.child,
);
}
Expand Down
8 changes: 4 additions & 4 deletions lib/src/editor/selection_menu/selection_menu_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ class SelectionMenu extends SelectionMenuService {

void calculateSelectionMenuOffset(Rect rect) {
// Workaround: We can customize the padding through the [EditorStyle],
// but the coordinates of overlay are not properly converted currently.
// Just subtract the padding here as a result.
// but the coordinates of overlay are not properly converted currently.
// Just subtract the padding here as a result.
const menuHeight = 200.0;
const menuOffset = Offset(0, 10);
final editorOffset =
Expand Down Expand Up @@ -223,13 +223,13 @@ class SelectionMenu extends SelectionMenuService {
}

// show on left
if (_offset.dx > editorWidth / 2) {
if (_offset.dx - editorOffset.dx > editorWidth / 2) {
_alignment = _alignment == Alignment.topLeft
? Alignment.topRight
: Alignment.bottomRight;

_offset = Offset(
editorWidth - _offset.dx,
editorWidth - _offset.dx + editorOffset.dx,
_offset.dy,
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class _MobileFloatingToolbarState extends State<MobileFloatingToolbar>
prevSelection = selection;
} else {
// uses debounce to avoid the computing the rects too frequently.
_clear();
_showAfterDelay(const Duration(milliseconds: 400));
}
}
Expand Down

0 comments on commit 1ea2a09

Please sign in to comment.