mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: auto pop up the menu after inserting image block (#3698)
This commit is contained in:
parent
8436bc6144
commit
11daa15b89
@ -9,6 +9,7 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/image/uplo
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart' hide UploadImageMenu;
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
@ -41,8 +42,13 @@ void main() {
|
||||
await tester.editor.tapSlashMenuItemWithName('Image');
|
||||
expect(find.byType(CustomImageBlockComponent), findsOneWidget);
|
||||
expect(find.byType(ImagePlaceholder), findsOneWidget);
|
||||
|
||||
await tester.tapButton(find.byType(ImagePlaceholder));
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byType(ImagePlaceholder),
|
||||
matching: find.byType(AppFlowyPopover),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.byType(UploadImageMenu), findsOneWidget);
|
||||
|
||||
final image = await rootBundle.load('assets/test/images/sample.jpeg');
|
||||
@ -84,8 +90,13 @@ void main() {
|
||||
await tester.editor.tapSlashMenuItemWithName('Image');
|
||||
expect(find.byType(CustomImageBlockComponent), findsOneWidget);
|
||||
expect(find.byType(ImagePlaceholder), findsOneWidget);
|
||||
|
||||
await tester.tapButton(find.byType(ImagePlaceholder));
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byType(ImagePlaceholder),
|
||||
matching: find.byType(AppFlowyPopover),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.byType(UploadImageMenu), findsOneWidget);
|
||||
|
||||
await tester.tapButtonWithName(
|
||||
@ -133,8 +144,13 @@ void main() {
|
||||
await tester.editor.tapSlashMenuItemWithName('Image');
|
||||
expect(find.byType(CustomImageBlockComponent), findsOneWidget);
|
||||
expect(find.byType(ImagePlaceholder), findsOneWidget);
|
||||
|
||||
await tester.tapButton(find.byType(ImagePlaceholder));
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byType(ImagePlaceholder),
|
||||
matching: find.byType(AppFlowyPopover),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.byType(UploadImageMenu), findsOneWidget);
|
||||
|
||||
await tester.tapButtonWithName(
|
||||
|
@ -3,6 +3,8 @@ import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
const kImagePlaceholderKey = 'imagePlaceholderKey';
|
||||
|
||||
typedef CustomImageBlockComponentMenuBuilder = Widget Function(
|
||||
Node node,
|
||||
CustomImageBlockComponentState state,
|
||||
@ -93,8 +95,10 @@ class CustomImageBlockComponentState extends State<CustomImageBlockComponent>
|
||||
MediaQuery.of(context).size.width;
|
||||
final height = attributes[ImageBlockKeys.height]?.toDouble();
|
||||
|
||||
final imagePlaceholderKey = node.extraInfos?[kImagePlaceholderKey];
|
||||
Widget child = src.isEmpty
|
||||
? ImagePlaceholder(
|
||||
key: imagePlaceholderKey is GlobalKey ? imagePlaceholderKey : null,
|
||||
node: node,
|
||||
)
|
||||
: ResizableImage(
|
||||
|
@ -28,10 +28,10 @@ class ImagePlaceholder extends StatefulWidget {
|
||||
final Node node;
|
||||
|
||||
@override
|
||||
State<ImagePlaceholder> createState() => _ImagePlaceholderState();
|
||||
State<ImagePlaceholder> createState() => ImagePlaceholderState();
|
||||
}
|
||||
|
||||
class _ImagePlaceholderState extends State<ImagePlaceholder> {
|
||||
class ImagePlaceholderState extends State<ImagePlaceholder> {
|
||||
final controller = PopoverController();
|
||||
late final editorState = context.read<EditorState>();
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/custom_image_block_component.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/image_placeholder.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
final customImageMenuItem = SelectionMenuItem(
|
||||
name: AppFlowyEditorLocalizations.current.image,
|
||||
@ -9,6 +12,54 @@ final customImageMenuItem = SelectionMenuItem(
|
||||
),
|
||||
keywords: ['image', 'picture', 'img', 'photo'],
|
||||
handler: (editorState, menuService, context) async {
|
||||
return await editorState.insertImageNode('');
|
||||
// use the key to retrieve the state of the image block to show the popover automatically
|
||||
final imagePlaceholderKey = GlobalKey<ImagePlaceholderState>();
|
||||
await editorState.insertEmptyImageBlock(imagePlaceholderKey);
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
imagePlaceholderKey.currentState?.controller.show();
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
extension InsertImage on EditorState {
|
||||
Future<void> insertEmptyImageBlock(GlobalKey key) async {
|
||||
final selection = this.selection;
|
||||
if (selection == null || !selection.isCollapsed) {
|
||||
return;
|
||||
}
|
||||
final node = getNodeAtPath(selection.end.path);
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
final emptyImage = imageNode(url: '')
|
||||
..extraInfos = {
|
||||
kImagePlaceholderKey: key,
|
||||
};
|
||||
final transaction = this.transaction;
|
||||
// if the current node is empty paragraph, replace it with image node
|
||||
if (node.type == ParagraphBlockKeys.type &&
|
||||
(node.delta?.isEmpty ?? false)) {
|
||||
transaction
|
||||
..insertNode(
|
||||
node.path,
|
||||
emptyImage,
|
||||
)
|
||||
..deleteNode(node);
|
||||
} else {
|
||||
transaction.insertNode(
|
||||
node.path.next,
|
||||
emptyImage,
|
||||
);
|
||||
}
|
||||
|
||||
transaction.afterSelection = Selection.collapsed(
|
||||
Position(
|
||||
path: node.path.next,
|
||||
offset: 0,
|
||||
),
|
||||
);
|
||||
|
||||
return apply(transaction);
|
||||
}
|
||||
}
|
||||
|
@ -54,8 +54,8 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: "194fe2f"
|
||||
resolved-ref: "194fe2fec9ce00baa2d5f2afbbfe0a45b3a7b158"
|
||||
ref: d1027c4
|
||||
resolved-ref: d1027c4d83a8cf78227e7d742c050ca945cef23a
|
||||
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
||||
source: git
|
||||
version: "1.4.4"
|
||||
@ -1890,4 +1890,4 @@ packages:
|
||||
version: "1.1.1"
|
||||
sdks:
|
||||
dart: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=3.10.1"
|
||||
flutter: ">=3.10.1"
|
||||
|
@ -47,7 +47,7 @@ dependencies:
|
||||
appflowy_editor:
|
||||
git:
|
||||
url: https://github.com/AppFlowy-IO/appflowy-editor.git
|
||||
ref: "194fe2f"
|
||||
ref: "d1027c4"
|
||||
appflowy_popover:
|
||||
path: packages/appflowy_popover
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user