diff --git a/frontend/appflowy_flutter/integration_test/desktop/database/database_view_test.dart b/frontend/appflowy_flutter/integration_test/desktop/database/database_view_test.dart index e35c9cc9d8..71656c1ea6 100644 --- a/frontend/appflowy_flutter/integration_test/desktop/database/database_view_test.dart +++ b/frontend/appflowy_flutter/integration_test/desktop/database/database_view_test.dart @@ -1,5 +1,10 @@ +import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/plugins/database/grid/presentation/grid_page.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/setting_entities.pbenum.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter_animate/flutter_animate.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; @@ -73,5 +78,37 @@ void main() { await tester.pumpAndSettle(); }); + + testWidgets('insert grid in column', (tester) async { + await tester.initializeAppFlowy(); + await tester.tapAnonymousSignInButton(); + + /// create page and show slash menu + await tester.createNewPageWithNameUnderParent(name: 'test page'); + await tester.editor.tapLineOfEditorAt(0); + await tester.editor.showSlashMenu(); + await tester.pumpAndSettle(); + + /// create a column + await tester.editor.tapSlashMenuItemWithName( + LocaleKeys.document_slashMenu_name_twoColumns.tr(), + ); + final actionList = find.byType(BlockActionList); + expect(actionList, findsNWidgets(2)); + final position = tester.getCenter(actionList.last); + + /// tap the second child of column + await tester.tapAt(position.copyWith(dx: position.dx + 50)); + + /// create a grid + await tester.editor.showSlashMenu(); + await tester.pumpAndSettle(); + await tester.editor.tapSlashMenuItemWithName( + LocaleKeys.document_slashMenu_name_grid.tr(), + ); + + final grid = find.byType(GridPageContent); + expect(grid, findsOneWidget); + }); }); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/tab_bar/tab_bar_view.dart b/frontend/appflowy_flutter/lib/plugins/database/tab_bar/tab_bar_view.dart index 3554f9112e..7c2dc40869 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/tab_bar/tab_bar_view.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/tab_bar/tab_bar_view.dart @@ -362,9 +362,13 @@ const kDatabasePluginWidgetBuilderActionBuilder = 'action_builder'; const kDatabasePluginWidgetBuilderNode = 'node'; class DatabasePluginWidgetBuilderSize { - const DatabasePluginWidgetBuilderSize({required this.horizontalPadding}); + const DatabasePluginWidgetBuilderSize({ + required this.horizontalPadding, + this.verticalPadding = 16.0, + }); final double horizontalPadding; + final double verticalPadding; } class DatabasePluginWidgetBuilder extends PluginWidgetBuilder { diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/built_in_page_widget.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/built_in_page_widget.dart index f96a06b21d..090ecdce78 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/built_in_page_widget.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/built_in_page_widget.dart @@ -1,3 +1,4 @@ +import 'package:appflowy/plugins/database/tab_bar/tab_bar_view.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart'; import 'package:appflowy/workspace/application/view/view_service.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pbserver.dart'; @@ -6,6 +7,7 @@ import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_result/appflowy_result.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class BuiltInPageWidget extends StatefulWidget { const BuiltInPageWidget({ @@ -77,6 +79,9 @@ class _BuiltInPageWidgetState extends State { } Widget _buildPage(BuildContext context, ViewPB view) { + final verticalPadding = + context.read()?.verticalPadding ?? + 0.0; return Focus( focusNode: focusNode, onFocusChange: (value) { @@ -85,7 +90,7 @@ class _BuiltInPageWidgetState extends State { } }, child: Padding( - padding: const EdgeInsets.symmetric(vertical: 16), + padding: EdgeInsets.symmetric(vertical: verticalPadding), child: widget.builder(view), ), ); diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/columns/simple_column_block_component.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/columns/simple_column_block_component.dart index 979dd92ce0..c426ad640f 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/columns/simple_column_block_component.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/columns/simple_column_block_component.dart @@ -1,3 +1,4 @@ +import 'package:appflowy/plugins/database/tab_bar/tab_bar_view.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/columns/simple_columns_block_constant.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:collection/collection.dart'; @@ -115,7 +116,11 @@ class SimpleColumnBlockComponentState extends State crossAxisAlignment: CrossAxisAlignment.start, children: node.children.map( (e) { - Widget child = IntrinsicHeight( + Widget child = Provider( + create: (_) => DatabasePluginWidgetBuilderSize( + verticalPadding: 0, + horizontalPadding: 0, + ), child: editorState.renderer.build(context, e), ); if (SimpleColumnsBlockConstants.enableDebugBorder) { diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/columns/simple_column_block_width_resizer.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/columns/simple_column_block_width_resizer.dart index f94056cd3a..69bec33c61 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/columns/simple_column_block_width_resizer.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/columns/simple_column_block_width_resizer.dart @@ -9,10 +9,12 @@ class SimpleColumnBlockWidthResizer extends StatefulWidget { super.key, required this.columnNode, required this.editorState, + this.height, }); final Node columnNode; final EditorState editorState; + final double? height; @override State createState() => @@ -53,15 +55,14 @@ class _SimpleColumnBlockWidthResizerState child: ValueListenableBuilder( valueListenable: isHovering, builder: (context, isHovering, child) { - if (isDraggingAppFlowyEditorBlock.value) { - return SizedBox.shrink(); - } + final hide = isDraggingAppFlowyEditorBlock.value || !isHovering; return MouseRegion( cursor: SystemMouseCursors.resizeLeftRight, child: Container( width: 2, + height: widget.height ?? 20, margin: EdgeInsets.symmetric(horizontal: 2), - color: isHovering + color: !hide ? Theme.of(context).colorScheme.primary : Colors.transparent, ), diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/columns/simple_columns_block_component.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/columns/simple_columns_block_component.dart index 8408c0f775..58ecde5f2f 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/columns/simple_columns_block_component.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/columns/simple_columns_block_component.dart @@ -92,17 +92,18 @@ class ColumnsBlockComponentState extends State final ScrollController scrollController = ScrollController(); + final ValueNotifier heightValueNotifier = ValueNotifier(null); + @override void initState() { super.initState(); - _updateColumnsBlock(); } @override void dispose() { scrollController.dispose(); - + heightValueNotifier.dispose(); super.dispose(); } @@ -110,15 +111,13 @@ class ColumnsBlockComponentState extends State Widget build(BuildContext context) { Widget child = Row( mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, + crossAxisAlignment: CrossAxisAlignment.start, children: _buildChildren(), ); child = Align( alignment: Alignment.topLeft, - child: IntrinsicHeight( - child: child, - ), + child: child, ); child = Padding( @@ -141,7 +140,10 @@ class ColumnsBlockComponentState extends State // the columns block does not support the block actions and selection // because the columns block is a layout wrapper, it does not have a content - return child; + return NotificationListener( + onNotification: (v) => updateHeightValueNotifier(v), + child: SizeChangedLayoutNotifier(child: child), + ); } List _buildChildren() { @@ -164,9 +166,15 @@ class ColumnsBlockComponentState extends State if (i != length - 1) { children.add( - SimpleColumnBlockWidthResizer( - columnNode: childNode, - editorState: editorState, + ValueListenableBuilder( + valueListenable: heightValueNotifier, + builder: (context, height, child) { + return SimpleColumnBlockWidthResizer( + columnNode: childNode, + editorState: editorState, + height: height, + ); + }, ), ); } @@ -194,6 +202,16 @@ class ColumnsBlockComponentState extends State } } + bool updateHeightValueNotifier(SizeChangedLayoutNotification notification) { + if (!mounted) return true; + final height = _renderBox?.size.height; + if (heightValueNotifier.value == height) return true; + WidgetsBinding.instance.addPostFrameCallback((_) { + heightValueNotifier.value = height; + }); + return true; + } + @override Position start() => Position(path: widget.node.path);