mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: image block issues (#3637)
This commit is contained in:
parent
a59561aee3
commit
d4bc575c03
@ -9,6 +9,7 @@ import 'document_option_action_test.dart' as document_option_action_test;
|
|||||||
import 'document_text_direction_test.dart' as document_text_direction_test;
|
import 'document_text_direction_test.dart' as document_text_direction_test;
|
||||||
import 'document_with_cover_image_test.dart' as document_with_cover_image_test;
|
import 'document_with_cover_image_test.dart' as document_with_cover_image_test;
|
||||||
import 'document_with_database_test.dart' as document_with_database_test;
|
import 'document_with_database_test.dart' as document_with_database_test;
|
||||||
|
import 'document_with_image_block_test.dart' as document_with_image_block_test;
|
||||||
import 'document_with_inline_math_equation_test.dart'
|
import 'document_with_inline_math_equation_test.dart'
|
||||||
as document_with_inline_math_equation_test;
|
as document_with_inline_math_equation_test;
|
||||||
import 'document_with_inline_page_test.dart' as document_with_inline_page_test;
|
import 'document_with_inline_page_test.dart' as document_with_inline_page_test;
|
||||||
@ -33,4 +34,5 @@ void startTesting() {
|
|||||||
document_alignment_test.main();
|
document_alignment_test.main();
|
||||||
document_text_direction_test.main();
|
document_text_direction_test.main();
|
||||||
document_option_action_test.main();
|
document_option_action_test.main();
|
||||||
|
document_with_image_block_test.main();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,147 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/custom_image_block_component.dart';
|
||||||
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/embed_image_url_widget.dart';
|
||||||
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/image_placeholder.dart';
|
||||||
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/unsplash_image_widget.dart';
|
||||||
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/upload_image_menu.dart';
|
||||||
|
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:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:integration_test/integration_test.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:run_with_network_images/run_with_network_images.dart';
|
||||||
|
|
||||||
|
import '../util/mock/mock_file_picker.dart';
|
||||||
|
import '../util/util.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
group('image block in document', () {
|
||||||
|
testWidgets('insert an image from local file', (tester) async {
|
||||||
|
await tester.initializeAppFlowy();
|
||||||
|
await tester.tapGoButton();
|
||||||
|
|
||||||
|
// create a new document
|
||||||
|
await tester.createNewPageWithName(
|
||||||
|
name: LocaleKeys.document_plugins_image_addAnImage.tr(),
|
||||||
|
layout: ViewLayoutPB.Document,
|
||||||
|
);
|
||||||
|
|
||||||
|
// tap the first line of the document
|
||||||
|
await tester.editor.tapLineOfEditorAt(0);
|
||||||
|
await tester.editor.showSlashMenu();
|
||||||
|
await tester.editor.tapSlashMenuItemWithName('Image');
|
||||||
|
expect(find.byType(CustomImageBlockComponent), findsOneWidget);
|
||||||
|
expect(find.byType(ImagePlaceholder), findsOneWidget);
|
||||||
|
|
||||||
|
await tester.tapButton(find.byType(ImagePlaceholder));
|
||||||
|
expect(find.byType(UploadImageMenu), findsOneWidget);
|
||||||
|
|
||||||
|
final image = await rootBundle.load('assets/test/images/sample.jpeg');
|
||||||
|
final tempDirectory = await getTemporaryDirectory();
|
||||||
|
final imagePath = p.join(tempDirectory.path, 'sample.jpeg');
|
||||||
|
final file = File(imagePath)
|
||||||
|
..writeAsBytesSync(image.buffer.asUint8List());
|
||||||
|
|
||||||
|
mockPickFilePaths(
|
||||||
|
paths: [imagePath],
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.tapButtonWithName(
|
||||||
|
LocaleKeys.document_imageBlock_upload_placeholder.tr(),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(find.byType(ResizableImage), findsOneWidget);
|
||||||
|
final node = tester.editor.getCurrentEditorState().getNodeAtPath([0])!;
|
||||||
|
expect(node.type, ImageBlockKeys.type);
|
||||||
|
expect(node.attributes[ImageBlockKeys.url], isNotEmpty);
|
||||||
|
|
||||||
|
// remove the temp file
|
||||||
|
file.deleteSync();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('insert an image from network', (tester) async {
|
||||||
|
await tester.initializeAppFlowy();
|
||||||
|
await tester.tapGoButton();
|
||||||
|
|
||||||
|
// create a new document
|
||||||
|
await tester.createNewPageWithName(
|
||||||
|
name: LocaleKeys.document_plugins_image_addAnImage.tr(),
|
||||||
|
layout: ViewLayoutPB.Document,
|
||||||
|
);
|
||||||
|
|
||||||
|
// tap the first line of the document
|
||||||
|
await tester.editor.tapLineOfEditorAt(0);
|
||||||
|
await tester.editor.showSlashMenu();
|
||||||
|
await tester.editor.tapSlashMenuItemWithName('Image');
|
||||||
|
expect(find.byType(CustomImageBlockComponent), findsOneWidget);
|
||||||
|
expect(find.byType(ImagePlaceholder), findsOneWidget);
|
||||||
|
|
||||||
|
await tester.tapButton(find.byType(ImagePlaceholder));
|
||||||
|
expect(find.byType(UploadImageMenu), findsOneWidget);
|
||||||
|
|
||||||
|
await tester.tapButtonWithName(
|
||||||
|
LocaleKeys.document_imageBlock_embedLink_label.tr(),
|
||||||
|
);
|
||||||
|
const url =
|
||||||
|
'https://images.unsplash.com/photo-1469474968028-56623f02e42e?ixlib=rb-4.0.3&q=85&fm=jpg&crop=entropy&cs=srgb&dl=david-marcu-78A265wPiO4-unsplash.jpg&w=640';
|
||||||
|
await tester.enterText(
|
||||||
|
find.descendant(
|
||||||
|
of: find.byType(EmbedImageUrlWidget),
|
||||||
|
matching: find.byType(TextField),
|
||||||
|
),
|
||||||
|
url,
|
||||||
|
);
|
||||||
|
await tester.tapButton(
|
||||||
|
find.descendant(
|
||||||
|
of: find.byType(EmbedImageUrlWidget),
|
||||||
|
matching: find.text(
|
||||||
|
LocaleKeys.document_imageBlock_embedLink_label.tr(),
|
||||||
|
findRichText: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(find.byType(ResizableImage), findsOneWidget);
|
||||||
|
final node = tester.editor.getCurrentEditorState().getNodeAtPath([0])!;
|
||||||
|
expect(node.type, ImageBlockKeys.type);
|
||||||
|
expect(node.attributes[ImageBlockKeys.url], url);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('insert an image from unsplash', (tester) async {
|
||||||
|
await runWithNetworkImages(() async {
|
||||||
|
await tester.initializeAppFlowy();
|
||||||
|
await tester.tapGoButton();
|
||||||
|
|
||||||
|
// create a new document
|
||||||
|
await tester.createNewPageWithName(
|
||||||
|
name: LocaleKeys.document_plugins_image_addAnImage.tr(),
|
||||||
|
layout: ViewLayoutPB.Document,
|
||||||
|
);
|
||||||
|
|
||||||
|
// tap the first line of the document
|
||||||
|
await tester.editor.tapLineOfEditorAt(0);
|
||||||
|
await tester.editor.showSlashMenu();
|
||||||
|
await tester.editor.tapSlashMenuItemWithName('Image');
|
||||||
|
expect(find.byType(CustomImageBlockComponent), findsOneWidget);
|
||||||
|
expect(find.byType(ImagePlaceholder), findsOneWidget);
|
||||||
|
|
||||||
|
await tester.tapButton(find.byType(ImagePlaceholder));
|
||||||
|
expect(find.byType(UploadImageMenu), findsOneWidget);
|
||||||
|
|
||||||
|
await tester.tapButtonWithName(
|
||||||
|
'Unsplash',
|
||||||
|
);
|
||||||
|
expect(find.byType(UnsplashImageWidget), findsOneWidget);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
@ -206,11 +206,8 @@ class CustomImageBlockComponentState extends State<CustomImageBlockComponent>
|
|||||||
Position position, {
|
Position position, {
|
||||||
bool shiftWithBaseOffset = false,
|
bool shiftWithBaseOffset = false,
|
||||||
}) {
|
}) {
|
||||||
if (_renderBox == null) {
|
final rects = getRectsInSelection(Selection.collapsed(position));
|
||||||
return null;
|
return rects.firstOrNull;
|
||||||
}
|
|
||||||
final size = _renderBox!.size;
|
|
||||||
return Rect.fromLTWH(-size.width / 2.0, 0, size.width, size.height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -41,13 +41,24 @@ class _ImagePlaceholderState extends State<ImagePlaceholder> {
|
|||||||
direction: PopoverDirection.bottomWithCenterAligned,
|
direction: PopoverDirection.bottomWithCenterAligned,
|
||||||
constraints: const BoxConstraints(
|
constraints: const BoxConstraints(
|
||||||
maxWidth: 540,
|
maxWidth: 540,
|
||||||
maxHeight: 260,
|
maxHeight: 360,
|
||||||
minHeight: 80,
|
minHeight: 80,
|
||||||
),
|
),
|
||||||
|
clickHandler: PopoverClickHandler.gestureDetector,
|
||||||
popupBuilder: (context) {
|
popupBuilder: (context) {
|
||||||
return UploadImageMenu(
|
return UploadImageMenu(
|
||||||
onPickFile: insertLocalImage,
|
onPickFile: (path) {
|
||||||
onSubmit: insertNetworkImage,
|
controller.close();
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||||
|
insertLocalImage(path);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onSubmit: (url) {
|
||||||
|
controller.close();
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||||
|
insertNetworkImage(url);
|
||||||
|
});
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: DecoratedBox(
|
child: DecoratedBox(
|
||||||
|
@ -50,29 +50,39 @@ class _UnsplashImageWidgetState extends State<UnsplashImageWidget> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
FlowyTextField(
|
Row(
|
||||||
autoFocus: true,
|
mainAxisSize: MainAxisSize.min,
|
||||||
hintText: LocaleKeys.document_imageBlock_searchForAnImage.tr(),
|
children: [
|
||||||
// textAlign: TextAlign.left,
|
Expanded(
|
||||||
onChanged: (value) => query = value,
|
child: FlowyTextField(
|
||||||
onEditingComplete: () => setState(() {
|
autoFocus: true,
|
||||||
randomPhotos = client.photos
|
hintText: LocaleKeys.document_imageBlock_searchForAnImage.tr(),
|
||||||
.random(
|
onChanged: (value) => query = value,
|
||||||
count: 18,
|
onEditingComplete: _search,
|
||||||
orientation: PhotoOrientation.landscape,
|
),
|
||||||
query: query,
|
),
|
||||||
)
|
const HSpace(4.0),
|
||||||
.goAndGet();
|
FlowyButton(
|
||||||
}),
|
useIntrinsicWidth: true,
|
||||||
|
text: FlowyText(
|
||||||
|
LocaleKeys.search_label.tr(),
|
||||||
|
),
|
||||||
|
onTap: _search,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const HSpace(12.0),
|
const VSpace(12.0),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: FutureBuilder(
|
child: FutureBuilder(
|
||||||
future: randomPhotos,
|
future: randomPhotos,
|
||||||
builder: (context, value) {
|
builder: (context, value) {
|
||||||
final data = value.data;
|
final data = value.data;
|
||||||
if (!value.hasData || data == null || data.isEmpty) {
|
if (!value.hasData ||
|
||||||
|
value.connectionState != ConnectionState.done ||
|
||||||
|
data == null ||
|
||||||
|
data.isEmpty) {
|
||||||
return const CircularProgressIndicator.adaptive();
|
return const CircularProgressIndicator.adaptive();
|
||||||
}
|
}
|
||||||
return GridView.count(
|
return GridView.count(
|
||||||
@ -97,6 +107,18 @@ class _UnsplashImageWidgetState extends State<UnsplashImageWidget> {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _search() {
|
||||||
|
setState(() {
|
||||||
|
randomPhotos = client.photos
|
||||||
|
.random(
|
||||||
|
count: 18,
|
||||||
|
orientation: PhotoOrientation.landscape,
|
||||||
|
query: query,
|
||||||
|
)
|
||||||
|
.goAndGet();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _UnsplashImage extends StatelessWidget {
|
class _UnsplashImage extends StatelessWidget {
|
||||||
@ -121,6 +143,7 @@ class _UnsplashImage extends StatelessWidget {
|
|||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const HSpace(2.0),
|
||||||
FlowyText(
|
FlowyText(
|
||||||
'by ${photo.name}',
|
'by ${photo.name}',
|
||||||
fontSize: 10.0,
|
fontSize: 10.0,
|
||||||
|
@ -6,7 +6,6 @@ import 'package:appflowy/workspace/application/appearance.dart';
|
|||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
@ -18,42 +17,28 @@ class BrightnessSetting extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FlowyTooltip.delayed(
|
return ThemeSettingEntryTemplateWidget(
|
||||||
margin: const EdgeInsets.only(left: 180),
|
label: LocaleKeys.settings_appearance_themeMode_label.tr(),
|
||||||
richMessage: themeModeTooltipTextSpan(
|
hint: hintText,
|
||||||
LocaleKeys.settings_appearance_themeMode_label.tr(),
|
onResetRequested: context.read<AppearanceSettingsCubit>().resetThemeMode,
|
||||||
),
|
trailing: [
|
||||||
child: ThemeSettingEntryTemplateWidget(
|
ThemeValueDropDown(
|
||||||
label: LocaleKeys.settings_appearance_themeMode_label.tr(),
|
currentValue: _themeModeLabelText(currentThemeMode),
|
||||||
onResetRequested:
|
popupBuilder: (context) => Column(
|
||||||
context.read<AppearanceSettingsCubit>().resetThemeMode,
|
mainAxisSize: MainAxisSize.min,
|
||||||
trailing: [
|
children: [
|
||||||
ThemeValueDropDown(
|
_themeModeItemButton(context, ThemeMode.light),
|
||||||
currentValue: _themeModeLabelText(currentThemeMode),
|
_themeModeItemButton(context, ThemeMode.dark),
|
||||||
popupBuilder: (context) => Column(
|
_themeModeItemButton(context, ThemeMode.system),
|
||||||
mainAxisSize: MainAxisSize.min,
|
],
|
||||||
children: [
|
|
||||||
_themeModeItemButton(context, ThemeMode.light),
|
|
||||||
_themeModeItemButton(context, ThemeMode.dark),
|
|
||||||
_themeModeItemButton(context, ThemeMode.system),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextSpan themeModeTooltipTextSpan(String hintText) => TextSpan(
|
String get hintText =>
|
||||||
children: [
|
'${LocaleKeys.settings_files_change.tr()} ${LocaleKeys.settings_appearance_themeMode_label.tr()} : ${Platform.isMacOS ? '⌘+Shift+L' : 'Ctrl+Shift+L'}';
|
||||||
TextSpan(
|
|
||||||
text: "${LocaleKeys.settings_files_change.tr()} $hintText\n",
|
|
||||||
),
|
|
||||||
TextSpan(
|
|
||||||
text: Platform.isMacOS ? "⌘+Shift+L" : "Ctrl+Shift+L",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
Widget _themeModeItemButton(
|
Widget _themeModeItemButton(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
|
@ -48,6 +48,11 @@ enum PopoverDirection {
|
|||||||
custom,
|
custom,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum PopoverClickHandler {
|
||||||
|
listener,
|
||||||
|
gestureDetector,
|
||||||
|
}
|
||||||
|
|
||||||
class Popover extends StatefulWidget {
|
class Popover extends StatefulWidget {
|
||||||
final PopoverController? controller;
|
final PopoverController? controller;
|
||||||
|
|
||||||
@ -78,11 +83,18 @@ class Popover extends StatefulWidget {
|
|||||||
|
|
||||||
final bool asBarrier;
|
final bool asBarrier;
|
||||||
|
|
||||||
|
/// The widget that will be used to trigger the popover.
|
||||||
|
///
|
||||||
|
/// Why do we need this?
|
||||||
|
/// Because if the parent widget of the popover is GestureDetector,
|
||||||
|
/// the conflict won't be resolve by using Listener, we want these two gestures exclusive.
|
||||||
|
final PopoverClickHandler clickHandler;
|
||||||
|
|
||||||
/// The content area of the popover.
|
/// The content area of the popover.
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
const Popover({
|
const Popover({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.child,
|
required this.child,
|
||||||
required this.popupBuilder,
|
required this.popupBuilder,
|
||||||
this.controller,
|
this.controller,
|
||||||
@ -97,7 +109,8 @@ class Popover extends StatefulWidget {
|
|||||||
this.onClose,
|
this.onClose,
|
||||||
this.canClose,
|
this.canClose,
|
||||||
this.asBarrier = false,
|
this.asBarrier = false,
|
||||||
}) : super(key: key);
|
this.clickHandler = PopoverClickHandler.listener,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<Popover> createState() => PopoverState();
|
State<Popover> createState() => PopoverState();
|
||||||
@ -203,9 +216,9 @@ class PopoverState extends State<Popover> {
|
|||||||
showOverlay();
|
showOverlay();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Listener(
|
child: _buildClickHandler(
|
||||||
child: widget.child,
|
widget.child,
|
||||||
onPointerDown: (_) {
|
() {
|
||||||
if (widget.triggerActions & PopoverTriggerFlags.click != 0) {
|
if (widget.triggerActions & PopoverTriggerFlags.click != 0) {
|
||||||
showOverlay();
|
showOverlay();
|
||||||
}
|
}
|
||||||
@ -213,6 +226,21 @@ class PopoverState extends State<Popover> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildClickHandler(Widget child, VoidCallback handler) {
|
||||||
|
switch (widget.clickHandler) {
|
||||||
|
case PopoverClickHandler.listener:
|
||||||
|
return Listener(
|
||||||
|
onPointerDown: (_) => handler(),
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
case PopoverClickHandler.gestureDetector:
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: handler,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PopoverContainer extends StatefulWidget {
|
class PopoverContainer extends StatefulWidget {
|
||||||
|
@ -18,8 +18,15 @@ class AppFlowyPopover extends StatelessWidget {
|
|||||||
final EdgeInsets windowPadding;
|
final EdgeInsets windowPadding;
|
||||||
final Decoration? decoration;
|
final Decoration? decoration;
|
||||||
|
|
||||||
|
/// The widget that will be used to trigger the popover.
|
||||||
|
///
|
||||||
|
/// Why do we need this?
|
||||||
|
/// Because if the parent widget of the popover is GestureDetector,
|
||||||
|
/// the conflict won't be resolve by using Listener, we want these two gestures exclusive.
|
||||||
|
final PopoverClickHandler clickHandler;
|
||||||
|
|
||||||
const AppFlowyPopover({
|
const AppFlowyPopover({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.child,
|
required this.child,
|
||||||
required this.popupBuilder,
|
required this.popupBuilder,
|
||||||
this.direction = PopoverDirection.rightWithTopAligned,
|
this.direction = PopoverDirection.rightWithTopAligned,
|
||||||
@ -34,7 +41,8 @@ class AppFlowyPopover extends StatelessWidget {
|
|||||||
this.margin = const EdgeInsets.all(6),
|
this.margin = const EdgeInsets.all(6),
|
||||||
this.windowPadding = const EdgeInsets.all(8.0),
|
this.windowPadding = const EdgeInsets.all(8.0),
|
||||||
this.decoration,
|
this.decoration,
|
||||||
}) : super(key: key);
|
this.clickHandler = PopoverClickHandler.listener,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -48,6 +56,7 @@ class AppFlowyPopover extends StatelessWidget {
|
|||||||
triggerActions: triggerActions,
|
triggerActions: triggerActions,
|
||||||
windowPadding: windowPadding,
|
windowPadding: windowPadding,
|
||||||
offset: offset,
|
offset: offset,
|
||||||
|
clickHandler: clickHandler,
|
||||||
popupBuilder: (context) {
|
popupBuilder: (context) {
|
||||||
final child = popupBuilder(context);
|
final child = popupBuilder(context);
|
||||||
return _PopoverContainer(
|
return _PopoverContainer(
|
||||||
|
@ -54,8 +54,8 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: e996c92
|
ref: af8d96b
|
||||||
resolved-ref: e996c9279d873f55a1b6aa919144763a60f83d32
|
resolved-ref: af8d96bc1aab07046f4febdd991e1787c75c6e38
|
||||||
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
||||||
source: git
|
source: git
|
||||||
version: "1.4.3"
|
version: "1.4.3"
|
||||||
@ -889,6 +889,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "1.0.4"
|
||||||
|
mockito:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: mockito
|
||||||
|
sha256: "8b46d7eb40abdda92d62edd01546051f0c27365e65608c284de336dccfef88cc"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.4.1"
|
||||||
mocktail:
|
mocktail:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1217,6 +1225,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.2"
|
version: "1.0.2"
|
||||||
|
run_with_network_images:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: run_with_network_images
|
||||||
|
sha256: "8bf2de4e5120ab24037eda09596408938aa8f5b09f6afabd49683bd01c7baa36"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.0.1"
|
||||||
rxdart:
|
rxdart:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -47,7 +47,7 @@ dependencies:
|
|||||||
appflowy_editor:
|
appflowy_editor:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/AppFlowy-IO/appflowy-editor.git
|
url: https://github.com/AppFlowy-IO/appflowy-editor.git
|
||||||
ref: 'e996c92'
|
ref: 'af8d96b'
|
||||||
appflowy_popover:
|
appflowy_popover:
|
||||||
path: packages/appflowy_popover
|
path: packages/appflowy_popover
|
||||||
|
|
||||||
@ -132,6 +132,8 @@ dev_dependencies:
|
|||||||
|
|
||||||
plugin_platform_interface: any
|
plugin_platform_interface: any
|
||||||
url_launcher_platform_interface: any
|
url_launcher_platform_interface: any
|
||||||
|
run_with_network_images: ^0.0.1
|
||||||
|
|
||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
http: ^1.0.0
|
http: ^1.0.0
|
||||||
|
Loading…
Reference in New Issue
Block a user