fix: block does not expand with grid size (#7745)

* fix: block does not expand with grid size

* fix: replace listenForSizeChanged with SizeChangedLayoutNotifier
This commit is contained in:
Morn 2025-04-15 13:50:53 +08:00 committed by GitHub
parent d01909830d
commit d9748d5ef1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 87 additions and 17 deletions

View File

@ -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-database2/setting_entities.pbenum.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.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:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart'; import 'package:integration_test/integration_test.dart';
@ -73,5 +78,37 @@ void main() {
await tester.pumpAndSettle(); 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);
});
}); });
} }

View File

@ -362,9 +362,13 @@ const kDatabasePluginWidgetBuilderActionBuilder = 'action_builder';
const kDatabasePluginWidgetBuilderNode = 'node'; const kDatabasePluginWidgetBuilderNode = 'node';
class DatabasePluginWidgetBuilderSize { class DatabasePluginWidgetBuilderSize {
const DatabasePluginWidgetBuilderSize({required this.horizontalPadding}); const DatabasePluginWidgetBuilderSize({
required this.horizontalPadding,
this.verticalPadding = 16.0,
});
final double horizontalPadding; final double horizontalPadding;
final double verticalPadding;
} }
class DatabasePluginWidgetBuilder extends PluginWidgetBuilder { class DatabasePluginWidgetBuilder extends PluginWidgetBuilder {

View File

@ -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/plugins/document/presentation/editor_plugins/plugins.dart';
import 'package:appflowy/workspace/application/view/view_service.dart'; import 'package:appflowy/workspace/application/view/view_service.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pbserver.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:appflowy_result/appflowy_result.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class BuiltInPageWidget extends StatefulWidget { class BuiltInPageWidget extends StatefulWidget {
const BuiltInPageWidget({ const BuiltInPageWidget({
@ -77,6 +79,9 @@ class _BuiltInPageWidgetState extends State<BuiltInPageWidget> {
} }
Widget _buildPage(BuildContext context, ViewPB view) { Widget _buildPage(BuildContext context, ViewPB view) {
final verticalPadding =
context.read<DatabasePluginWidgetBuilderSize?>()?.verticalPadding ??
0.0;
return Focus( return Focus(
focusNode: focusNode, focusNode: focusNode,
onFocusChange: (value) { onFocusChange: (value) {
@ -85,7 +90,7 @@ class _BuiltInPageWidgetState extends State<BuiltInPageWidget> {
} }
}, },
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16), padding: EdgeInsets.symmetric(vertical: verticalPadding),
child: widget.builder(view), child: widget.builder(view),
), ),
); );

View File

@ -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/plugins/document/presentation/editor_plugins/columns/simple_columns_block_constant.dart';
import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
@ -115,7 +116,11 @@ class SimpleColumnBlockComponentState extends State<SimpleColumnBlockComponent>
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: node.children.map( children: node.children.map(
(e) { (e) {
Widget child = IntrinsicHeight( Widget child = Provider(
create: (_) => DatabasePluginWidgetBuilderSize(
verticalPadding: 0,
horizontalPadding: 0,
),
child: editorState.renderer.build(context, e), child: editorState.renderer.build(context, e),
); );
if (SimpleColumnsBlockConstants.enableDebugBorder) { if (SimpleColumnsBlockConstants.enableDebugBorder) {

View File

@ -9,10 +9,12 @@ class SimpleColumnBlockWidthResizer extends StatefulWidget {
super.key, super.key,
required this.columnNode, required this.columnNode,
required this.editorState, required this.editorState,
this.height,
}); });
final Node columnNode; final Node columnNode;
final EditorState editorState; final EditorState editorState;
final double? height;
@override @override
State<SimpleColumnBlockWidthResizer> createState() => State<SimpleColumnBlockWidthResizer> createState() =>
@ -53,15 +55,14 @@ class _SimpleColumnBlockWidthResizerState
child: ValueListenableBuilder<bool>( child: ValueListenableBuilder<bool>(
valueListenable: isHovering, valueListenable: isHovering,
builder: (context, isHovering, child) { builder: (context, isHovering, child) {
if (isDraggingAppFlowyEditorBlock.value) { final hide = isDraggingAppFlowyEditorBlock.value || !isHovering;
return SizedBox.shrink();
}
return MouseRegion( return MouseRegion(
cursor: SystemMouseCursors.resizeLeftRight, cursor: SystemMouseCursors.resizeLeftRight,
child: Container( child: Container(
width: 2, width: 2,
height: widget.height ?? 20,
margin: EdgeInsets.symmetric(horizontal: 2), margin: EdgeInsets.symmetric(horizontal: 2),
color: isHovering color: !hide
? Theme.of(context).colorScheme.primary ? Theme.of(context).colorScheme.primary
: Colors.transparent, : Colors.transparent,
), ),

View File

@ -92,17 +92,18 @@ class ColumnsBlockComponentState extends State<ColumnsBlockComponent>
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
final ValueNotifier<double?> heightValueNotifier = ValueNotifier(null);
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_updateColumnsBlock(); _updateColumnsBlock();
} }
@override @override
void dispose() { void dispose() {
scrollController.dispose(); scrollController.dispose();
heightValueNotifier.dispose();
super.dispose(); super.dispose();
} }
@ -110,15 +111,13 @@ class ColumnsBlockComponentState extends State<ColumnsBlockComponent>
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget child = Row( Widget child = Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.start,
children: _buildChildren(), children: _buildChildren(),
); );
child = Align( child = Align(
alignment: Alignment.topLeft, alignment: Alignment.topLeft,
child: IntrinsicHeight( child: child,
child: child,
),
); );
child = Padding( child = Padding(
@ -141,7 +140,10 @@ class ColumnsBlockComponentState extends State<ColumnsBlockComponent>
// the columns block does not support the block actions and selection // 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 // because the columns block is a layout wrapper, it does not have a content
return child; return NotificationListener<SizeChangedLayoutNotification>(
onNotification: (v) => updateHeightValueNotifier(v),
child: SizeChangedLayoutNotifier(child: child),
);
} }
List<Widget> _buildChildren() { List<Widget> _buildChildren() {
@ -164,9 +166,15 @@ class ColumnsBlockComponentState extends State<ColumnsBlockComponent>
if (i != length - 1) { if (i != length - 1) {
children.add( children.add(
SimpleColumnBlockWidthResizer( ValueListenableBuilder(
columnNode: childNode, valueListenable: heightValueNotifier,
editorState: editorState, builder: (context, height, child) {
return SimpleColumnBlockWidthResizer(
columnNode: childNode,
editorState: editorState,
height: height,
);
},
), ),
); );
} }
@ -194,6 +202,16 @@ class ColumnsBlockComponentState extends State<ColumnsBlockComponent>
} }
} }
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 @override
Position start() => Position(path: widget.node.path); Position start() => Position(path: widget.node.path);