fix: rect of the divider block is incorrect (#415)
* fix: rect of the divider block is incorrect * fix: only show the context menu when the gesture hit the selection area * chore: change image upload widget UI * fix: context menu test
This commit is contained in:
parent
81186fa857
commit
a9af2bbd37
4 changed files with 58 additions and 27 deletions
|
|
@ -124,7 +124,7 @@ class _DividerBlockComponentWidgetState
|
|||
|
||||
@override
|
||||
Rect getBlockRect() {
|
||||
return getCursorRectInPosition(Position.invalid()) ?? Rect.zero;
|
||||
return getRectsInSelection(Selection.invalid()).first;
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../util/file_picker/file_picker_impl.dart';
|
||||
import 'package:file_picker/file_picker.dart' as fp;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../util/file_picker/file_picker_impl.dart';
|
||||
|
||||
enum ImageFromFileStatus {
|
||||
notSelected,
|
||||
|
|
@ -47,7 +48,7 @@ void showImageMenu(
|
|||
builder: (context) => UploadImageMenu(
|
||||
backgroundColor: menuService.style.selectionMenuBackgroundColor,
|
||||
headerColor: menuService.style.selectionMenuItemTextColor,
|
||||
width: MediaQuery.of(context).size.width * 0.4,
|
||||
width: MediaQuery.of(context).size.width * 0.3,
|
||||
onSubmitted: insertImage,
|
||||
onUpload: insertImage,
|
||||
),
|
||||
|
|
@ -103,8 +104,8 @@ class _UploadImageMenuState extends State<UploadImageMenu> {
|
|||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: widget.width,
|
||||
height: 300,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 10.0),
|
||||
height: 240,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 5.0),
|
||||
decoration: BoxDecoration(
|
||||
color: widget.backgroundColor,
|
||||
boxShadow: [
|
||||
|
|
@ -123,7 +124,8 @@ class _UploadImageMenuState extends State<UploadImageMenu> {
|
|||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: SizedBox(
|
||||
width: 300,
|
||||
width: 260,
|
||||
height: 36,
|
||||
child: TabBar(
|
||||
tabs: const [
|
||||
Tab(text: 'Upload Image'),
|
||||
|
|
@ -207,7 +209,7 @@ class _UploadImageMenuState extends State<UploadImageMenu> {
|
|||
) {
|
||||
return SizedBox(
|
||||
width: 170,
|
||||
height: 48,
|
||||
height: 36,
|
||||
child: TextButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateProperty.all(const Color(0xFF00BCF0)),
|
||||
|
|
@ -296,7 +298,7 @@ class _UploadImageMenuState extends State<UploadImageMenu> {
|
|||
}
|
||||
},
|
||||
child: Container(
|
||||
height: 80,
|
||||
height: 60,
|
||||
margin: const EdgeInsets.all(10.0),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: const Color(0xff00BCF0)),
|
||||
|
|
|
|||
|
|
@ -529,6 +529,25 @@ class _DesktopSelectionServiceWidgetState
|
|||
void _showContextMenu(TapDownDetails details) {
|
||||
_clearContextMenu();
|
||||
|
||||
// only shows around the selection area.
|
||||
if (selectionRects.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
final isHitSelectionAreas = currentSelection.value?.isCollapsed == true ||
|
||||
selectionRects.any((element) {
|
||||
const threshold = 20;
|
||||
final scaledArea = Rect.fromCenter(
|
||||
center: element.center,
|
||||
width: element.width + threshold,
|
||||
height: element.height + threshold,
|
||||
);
|
||||
return scaledArea.contains(details.globalPosition);
|
||||
});
|
||||
if (!isHitSelectionAreas) {
|
||||
return;
|
||||
}
|
||||
|
||||
// For now, only support the text node.
|
||||
if (!currentSelectedNodes.every((element) => element.delta != null)) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flutter/gestures.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 '../new/infra/testable_editor.dart';
|
||||
|
|
@ -26,9 +26,10 @@ void main() async {
|
|||
});
|
||||
});
|
||||
group('context menu test', () {
|
||||
void rightClick() {
|
||||
void rightClickAt(Offset position) {
|
||||
GestureBinding.instance.handlePointerEvent(
|
||||
const PointerDownEvent(
|
||||
PointerDownEvent(
|
||||
position: position,
|
||||
buttons: kSecondaryMouseButton,
|
||||
),
|
||||
);
|
||||
|
|
@ -39,22 +40,26 @@ void main() async {
|
|||
}
|
||||
|
||||
testWidgets('context menu test', (tester) async {
|
||||
final editor = tester.editor
|
||||
..addParagraph(initialText: 'Welcome to AppFlowy');
|
||||
const text = 'Welcome to AppFlowy';
|
||||
final editor = tester.editor..addParagraph(initialText: text);
|
||||
await editor.startTesting();
|
||||
expect(find.byType(ContextMenu), findsNothing);
|
||||
rightClick();
|
||||
await editor.updateSelection(
|
||||
Selection.single(path: [0], startOffset: 0, endOffset: text.length),
|
||||
);
|
||||
final position = tester.getCenter(find.text(text, findRichText: true));
|
||||
rightClickAt(position);
|
||||
await tester.pump();
|
||||
expect(find.byType(ContextMenu), findsOneWidget);
|
||||
await editor.dispose();
|
||||
});
|
||||
|
||||
testWidgets('context menu cut test ', (tester) async {
|
||||
final editor = tester.editor
|
||||
..addParagraph(initialText: 'Welcome to AppFlowy');
|
||||
const text = 'Welcome to AppFlowy';
|
||||
final editor = tester.editor..addParagraph(initialText: text);
|
||||
await editor.startTesting();
|
||||
expect(
|
||||
find.text('Welcome to AppFlowy', findRichText: true),
|
||||
find.text(text, findRichText: true),
|
||||
findsOneWidget,
|
||||
);
|
||||
await editor.updateSelection(
|
||||
|
|
@ -63,9 +68,10 @@ void main() async {
|
|||
end: Position(path: [0], offset: 18),
|
||||
),
|
||||
);
|
||||
final text =
|
||||
final copiedText =
|
||||
editor.editorState.getTextInSelection(editor.selection).join('/n');
|
||||
rightClick();
|
||||
final position = tester.getCenter(find.text(text, findRichText: true));
|
||||
rightClickAt(position);
|
||||
await tester.pump();
|
||||
final cutButton = find.text('Cut');
|
||||
expect(cutButton, findsOneWidget);
|
||||
|
|
@ -76,17 +82,18 @@ void main() async {
|
|||
findsNothing,
|
||||
);
|
||||
final clipBoardData = await AppFlowyClipboard.getData();
|
||||
expect(clipBoardData.text, text);
|
||||
expect(clipBoardData.text, copiedText);
|
||||
await editor.dispose();
|
||||
});
|
||||
|
||||
testWidgets('context menu copy and paste test', (tester) async {
|
||||
const text = 'Welcome to AppFlowy';
|
||||
final editor = tester.editor
|
||||
..addParagraph(initialText: 'Welcome to AppFlowy');
|
||||
editor.addParagraph(initialText: 'Hello');
|
||||
..addParagraph(initialText: text)
|
||||
..addParagraph(initialText: 'Hello');
|
||||
await editor.startTesting();
|
||||
expect(
|
||||
find.text('Welcome to AppFlowy', findRichText: true),
|
||||
find.text(text, findRichText: true),
|
||||
findsOneWidget,
|
||||
);
|
||||
await editor.updateSelection(
|
||||
|
|
@ -95,9 +102,10 @@ void main() async {
|
|||
end: Position(path: [1], offset: 5),
|
||||
),
|
||||
);
|
||||
final text =
|
||||
final copiedText =
|
||||
editor.editorState.getTextInSelection(editor.selection).join('/n');
|
||||
rightClick();
|
||||
final position = tester.getCenter(find.text('Hello', findRichText: true));
|
||||
rightClickAt(position);
|
||||
await tester.pump();
|
||||
final copyButton = find.text('Copy');
|
||||
expect(copyButton, findsOneWidget);
|
||||
|
|
@ -108,14 +116,16 @@ void main() async {
|
|||
findsOneWidget,
|
||||
);
|
||||
final clipBoardData = await AppFlowyClipboard.getData();
|
||||
expect(clipBoardData.text, text);
|
||||
expect(clipBoardData.text, copiedText);
|
||||
await editor.updateSelection(
|
||||
Selection(
|
||||
start: Position(path: [0], offset: 0),
|
||||
end: Position(path: [0], offset: 7),
|
||||
),
|
||||
);
|
||||
rightClick();
|
||||
final newPosition =
|
||||
tester.getTopLeft(find.text(text, findRichText: true));
|
||||
rightClickAt(newPosition);
|
||||
await tester.pump();
|
||||
final pasteButton = find.text('Paste');
|
||||
expect(pasteButton, findsOneWidget);
|
||||
|
|
|
|||
Loading…
Reference in a new issue