fix: toggle heading issues (#6714)

* fix: pages overflow when selecting homepage

* fix: toggle heading issues

* Revert "fix: pages overflow when selecting homepage"

This reverts commit 156882a9a7e039a38cd206306e19b94eb391f948.

* chore: optimize code logic

* fix: assertion in toggle list

* fix: make the turn into menu and color menu exclusive

* test: add toggle heading test
This commit is contained in:
Lucas 2024-11-05 10:52:22 +08:00 committed by GitHub
parent 54096b391f
commit 82effbf8e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 298 additions and 82 deletions

View File

@ -1,6 +1,8 @@
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.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';
@ -60,6 +62,50 @@ void main() {
findsNWidgets(6), findsNWidgets(6),
); );
}); });
testWidgets('insert toggle heading and convert it to heading',
(tester) async {
await tester.initializeAppFlowy();
await tester.tapAnonymousSignInButton();
await tester.createNewPageWithNameUnderParent(
name: 'toggle heading block test',
);
await tester.editor.tapLineOfEditorAt(0);
await tester.ime.insertText('# > $_heading1\n');
await tester.simulateKeyEvent(LogicalKeyboardKey.enter);
await tester.ime.insertText('item 1');
await tester.pumpAndSettle();
await tester.editor.updateSelection(
Selection(
start: Position(path: [0]),
end: Position(path: [0], offset: _heading1.length),
),
);
await tester.tapButton(find.byType(HeadingPopup));
await tester.pumpAndSettle();
expect(
find.byType(HeadingButton),
findsNWidgets(3),
);
// tap the H1 button
await tester.tapButton(find.byType(HeadingButton).at(0));
await tester.pumpAndSettle();
final editorState = tester.editor.getCurrentEditorState();
final node1 = editorState.document.nodeAtPath([0])!;
expect(node1.type, HeadingBlockKeys.type);
expect(node1.attributes[HeadingBlockKeys.level], 1);
final node2 = editorState.document.nodeAtPath([1])!;
expect(node2.type, ParagraphBlockKeys.type);
expect(node2.delta!.toPlainText(), 'item 1');
});
}); });
} }

View File

@ -231,7 +231,6 @@ class _DocumentPageState extends State<DocumentPage>
final Path? path = _getPathFromAction(action, editorState); final Path? path = _getPathFromAction(action, editorState);
if (path != null) { if (path != null) {
debugPrint('jump to block: $path');
editorState.updateSelectionWithReason( editorState.updateSelectionWithReason(
Selection.collapsed(Position(path: path)), Selection.collapsed(Position(path: path)),
); );

View File

@ -134,12 +134,19 @@ void _customBlockOptionActions(
); );
builder.actionBuilder = (context, state) { builder.actionBuilder = (context, state) {
final top = builder.configuration.padding(context.node).top; double top = builder.configuration.padding(context.node).top;
final padding = context.node.type == HeadingBlockKeys.type final type = context.node.type;
? EdgeInsets.only(top: top + 8.0) final level = context.node.attributes[HeadingBlockKeys.level] ?? 0;
: EdgeInsets.only(top: top + 2.0); if ((type == HeadingBlockKeys.type ||
type == ToggleListBlockKeys.type) &&
level > 0) {
final offset = [14.0, 11.0, 8.0, 6.0, 4.0, 2.0];
top += offset[level - 1];
} else {
top += 2.0;
}
return Padding( return Padding(
padding: padding, padding: EdgeInsets.only(top: top),
child: BlockActionList( child: BlockActionList(
blockComponentContext: context, blockComponentContext: context,
blockComponentState: state, blockComponentState: state,

View File

@ -9,7 +9,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'drag_to_reorder/draggable_option_button.dart'; import 'drag_to_reorder/draggable_option_button.dart';
class BlockOptionButton extends StatelessWidget { class BlockOptionButton extends StatefulWidget {
const BlockOptionButton({ const BlockOptionButton({
super.key, super.key,
required this.blockComponentContext, required this.blockComponentContext,
@ -25,6 +25,16 @@ class BlockOptionButton extends StatelessWidget {
final EditorState editorState; final EditorState editorState;
final Map<String, BlockComponentBuilder> blockComponentBuilder; final Map<String, BlockComponentBuilder> blockComponentBuilder;
@override
State<BlockOptionButton> createState() => _BlockOptionButtonState();
}
class _BlockOptionButtonState extends State<BlockOptionButton> {
// the mutex is used to ensure that only one popover is open at a time
// for example, when the user is selecting the color, the turn into option
// should not be shown.
final mutex = PopoverMutex();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final direction = final direction =
@ -34,8 +44,8 @@ class BlockOptionButton extends StatelessWidget {
: PopoverDirection.leftWithCenterAligned; : PopoverDirection.leftWithCenterAligned;
return BlocProvider( return BlocProvider(
create: (context) => BlockActionOptionCubit( create: (context) => BlockActionOptionCubit(
editorState: editorState, editorState: widget.editorState,
blockComponentBuilder: blockComponentBuilder, blockComponentBuilder: widget.blockComponentBuilder,
), ),
child: BlocBuilder<BlockActionOptionCubit, BlockActionOptionState>( child: BlocBuilder<BlockActionOptionCubit, BlockActionOptionState>(
builder: (context, _) => PopoverActionList<PopoverAction>( builder: (context, _) => PopoverActionList<PopoverAction>(
@ -55,30 +65,41 @@ class BlockOptionButton extends StatelessWidget {
), ),
buildChild: (controller) => DraggableOptionButton( buildChild: (controller) => DraggableOptionButton(
controller: controller, controller: controller,
editorState: editorState, editorState: widget.editorState,
blockComponentContext: blockComponentContext, blockComponentContext: widget.blockComponentContext,
blockComponentBuilder: blockComponentBuilder, blockComponentBuilder: widget.blockComponentBuilder,
), ),
), ),
), ),
); );
} }
@override
void dispose() {
mutex.dispose();
super.dispose();
}
List<PopoverAction> _buildPopoverActions(BuildContext context) { List<PopoverAction> _buildPopoverActions(BuildContext context) {
return actions.map((e) { return widget.actions.map((e) {
switch (e) { switch (e) {
case OptionAction.divider: case OptionAction.divider:
return DividerOptionAction(); return DividerOptionAction();
case OptionAction.color: case OptionAction.color:
return ColorOptionAction(editorState: editorState); return ColorOptionAction(
editorState: widget.editorState,
mutex: mutex,
);
case OptionAction.align: case OptionAction.align:
return AlignOptionAction(editorState: editorState); return AlignOptionAction(editorState: widget.editorState);
case OptionAction.depth: case OptionAction.depth:
return DepthOptionAction(editorState: editorState); return DepthOptionAction(editorState: widget.editorState);
case OptionAction.turnInto: case OptionAction.turnInto:
return TurnIntoOptionAction( return TurnIntoOptionAction(
editorState: editorState, editorState: widget.editorState,
blockComponentBuilder: blockComponentBuilder, blockComponentBuilder: widget.blockComponentBuilder,
mutex: mutex,
); );
default: default:
return OptionActionWrapper(e); return OptionActionWrapper(e);
@ -88,15 +109,17 @@ class BlockOptionButton extends StatelessWidget {
void _onPopoverBuilder() { void _onPopoverBuilder() {
keepEditorFocusNotifier.increase(); keepEditorFocusNotifier.increase();
blockComponentState.alwaysShowActions = true; widget.blockComponentState.alwaysShowActions = true;
} }
void _onPopoverClosed(BuildContext context) { void _onPopoverClosed(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) { WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
editorState.selectionType = null; widget.editorState.selectionType = null;
editorState.selection = null; widget.editorState.selection = null;
blockComponentState.alwaysShowActions = false; widget.blockComponentState.alwaysShowActions = false;
}); });
PopoverContainer.maybeOf(context)?.closeAll();
} }
void _onActionSelected( void _onActionSelected(
@ -110,7 +133,7 @@ class BlockOptionButton extends StatelessWidget {
context.read<BlockActionOptionCubit>().handleAction( context.read<BlockActionOptionCubit>().handleAction(
action.inner, action.inner,
blockComponentContext.node, widget.blockComponentContext.node,
); );
controller.close(); controller.close();
} }

View File

@ -389,6 +389,14 @@ class BlockActionOptionCubit extends Cubit<BlockActionOptionState> {
]); ]);
if (afterSelection != null) { if (afterSelection != null) {
transaction.afterSelection = afterSelection; transaction.afterSelection = afterSelection;
} else if (insertedNodes.isNotEmpty) {
// select the blocks
transaction.afterSelection = Selection(
start: Position(path: node.path.child(0)),
end: Position(path: node.path.child(insertedNodes.length - 1)),
);
} else {
transaction.afterSelection = transaction.beforeSelection;
} }
await editorState.apply(transaction); await editorState.apply(transaction);

View File

@ -13,10 +13,12 @@ const optionActionColorDefaultColor = 'appflowy_theme_default_color';
class ColorOptionAction extends CustomActionCell { class ColorOptionAction extends CustomActionCell {
ColorOptionAction({ ColorOptionAction({
required this.editorState, required this.editorState,
required this.mutex,
}); });
final EditorState editorState; final EditorState editorState;
final PopoverController innerController = PopoverController(); final PopoverController innerController = PopoverController();
final PopoverMutex mutex;
@override @override
Widget buildWithContext( Widget buildWithContext(
@ -24,16 +26,49 @@ class ColorOptionAction extends CustomActionCell {
PopoverController controller, PopoverController controller,
PopoverMutex? mutex, PopoverMutex? mutex,
) { ) {
return ColorOptionButton(
editorState: editorState,
mutex: this.mutex,
controller: controller,
);
}
}
class ColorOptionButton extends StatefulWidget {
const ColorOptionButton({
super.key,
required this.editorState,
required this.mutex,
required this.controller,
});
final EditorState editorState;
final PopoverMutex mutex;
final PopoverController controller;
@override
State<ColorOptionButton> createState() => _ColorOptionButtonState();
}
class _ColorOptionButtonState extends State<ColorOptionButton> {
final PopoverController innerController = PopoverController();
bool isOpen = false;
@override
Widget build(BuildContext context) {
return AppFlowyPopover( return AppFlowyPopover(
asBarrier: true, asBarrier: true,
controller: innerController, controller: innerController,
mutex: mutex, mutex: widget.mutex,
popupBuilder: (context) => _buildColorOptionMenu( popupBuilder: (context) {
context, isOpen = true;
controller, return _buildColorOptionMenu(
), context,
widget.controller,
);
},
onClose: () => isOpen = false,
direction: PopoverDirection.rightWithCenterAligned, direction: PopoverDirection.rightWithCenterAligned,
offset: const Offset(10, 0),
animationDuration: Durations.short3, animationDuration: Durations.short3,
beginScaleFactor: 1.0, beginScaleFactor: 1.0,
beginOpacity: 0.8, beginOpacity: 0.8,
@ -45,7 +80,9 @@ class ColorOptionAction extends CustomActionCell {
), ),
name: LocaleKeys.document_plugins_optionAction_color.tr(), name: LocaleKeys.document_plugins_optionAction_color.tr(),
onTap: () { onTap: () {
innerController.show(); if (!isOpen) {
innerController.show();
}
}, },
), ),
); );
@ -55,12 +92,12 @@ class ColorOptionAction extends CustomActionCell {
BuildContext context, BuildContext context,
PopoverController controller, PopoverController controller,
) { ) {
final selection = editorState.selection?.normalized; final selection = widget.editorState.selection?.normalized;
if (selection == null) { if (selection == null) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
final node = editorState.getNodeAtPath(selection.start.path); final node = widget.editorState.getNodeAtPath(selection.start.path);
if (node == null) { if (node == null) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
@ -73,11 +110,11 @@ class ColorOptionAction extends CustomActionCell {
Node node, Node node,
PopoverController controller, PopoverController controller,
) { ) {
final selection = editorState.selection?.normalized; final selection = widget.editorState.selection?.normalized;
if (selection == null) { if (selection == null) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
final node = editorState.getNodeAtPath(selection.start.path); final node = widget.editorState.getNodeAtPath(selection.start.path);
if (node == null) { if (node == null) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
@ -110,11 +147,11 @@ class ColorOptionAction extends CustomActionCell {
color: AFThemeExtension.of(context).onBackground, color: AFThemeExtension.of(context).onBackground,
), ),
onTap: (option, index) async { onTap: (option, index) async {
final transaction = editorState.transaction; final transaction = widget.editorState.transaction;
transaction.updateNode(node, { transaction.updateNode(node, {
blockComponentBackgroundColor: option.id, blockComponentBackgroundColor: option.id,
}); });
await editorState.apply(transaction); await widget.editorState.apply(transaction);
innerController.close(); innerController.close();
controller.close(); controller.close();

View File

@ -15,11 +15,13 @@ class TurnIntoOptionAction extends CustomActionCell {
TurnIntoOptionAction({ TurnIntoOptionAction({
required this.editorState, required this.editorState,
required this.blockComponentBuilder, required this.blockComponentBuilder,
required this.mutex,
}); });
final EditorState editorState; final EditorState editorState;
final Map<String, BlockComponentBuilder> blockComponentBuilder; final Map<String, BlockComponentBuilder> blockComponentBuilder;
final PopoverController innerController = PopoverController(); final PopoverController innerController = PopoverController();
final PopoverMutex mutex;
@override @override
Widget buildWithContext( Widget buildWithContext(
@ -27,21 +29,54 @@ class TurnIntoOptionAction extends CustomActionCell {
PopoverController controller, PopoverController controller,
PopoverMutex? mutex, PopoverMutex? mutex,
) { ) {
return TurnInfoButton(
editorState: editorState,
blockComponentBuilder: blockComponentBuilder,
mutex: this.mutex,
);
}
}
class TurnInfoButton extends StatefulWidget {
const TurnInfoButton({
super.key,
required this.editorState,
required this.blockComponentBuilder,
required this.mutex,
});
final EditorState editorState;
final Map<String, BlockComponentBuilder> blockComponentBuilder;
final PopoverMutex mutex;
@override
State<TurnInfoButton> createState() => _TurnInfoButtonState();
}
class _TurnInfoButtonState extends State<TurnInfoButton> {
final PopoverController innerController = PopoverController();
bool isOpen = false;
@override
Widget build(BuildContext context) {
return AppFlowyPopover( return AppFlowyPopover(
asBarrier: true, asBarrier: true,
controller: innerController, controller: innerController,
mutex: mutex, mutex: widget.mutex,
popupBuilder: (context) => BlocProvider<BlockActionOptionCubit>( popupBuilder: (context) {
create: (_) => BlockActionOptionCubit( isOpen = true;
editorState: editorState, return BlocProvider<BlockActionOptionCubit>(
blockComponentBuilder: blockComponentBuilder, create: (context) => BlockActionOptionCubit(
), editorState: widget.editorState,
child: BlocBuilder<BlockActionOptionCubit, BlockActionOptionState>( blockComponentBuilder: widget.blockComponentBuilder,
builder: (context, _) => _buildTurnIntoOptionMenu(context), ),
), child: BlocBuilder<BlockActionOptionCubit, BlockActionOptionState>(
), builder: (context, _) => _buildTurnIntoOptionMenu(context),
),
);
},
onClose: () => isOpen = false,
direction: PopoverDirection.rightWithCenterAligned, direction: PopoverDirection.rightWithCenterAligned,
offset: const Offset(10, 0),
animationDuration: Durations.short3, animationDuration: Durations.short3,
beginScaleFactor: 1.0, beginScaleFactor: 1.0,
beginOpacity: 0.8, beginOpacity: 0.8,
@ -50,13 +85,17 @@ class TurnIntoOptionAction extends CustomActionCell {
// todo(lucas): replace the svg with the correct one // todo(lucas): replace the svg with the correct one
leftIcon: const FlowySvg(FlowySvgs.turninto_s), leftIcon: const FlowySvg(FlowySvgs.turninto_s),
name: LocaleKeys.document_plugins_optionAction_turnInto.tr(), name: LocaleKeys.document_plugins_optionAction_turnInto.tr(),
onTap: innerController.show, onTap: () {
if (!isOpen) {
innerController.show();
}
},
), ),
); );
} }
Widget _buildTurnIntoOptionMenu(BuildContext context) { Widget _buildTurnIntoOptionMenu(BuildContext context) {
final selection = editorState.selection?.normalized; final selection = widget.editorState.selection?.normalized;
// the selection may not be collapsed, for example, if a block contains some children, // the selection may not be collapsed, for example, if a block contains some children,
// the selection will be the start from the current block and end at the last child block. // the selection will be the start from the current block and end at the last child block.
// we should take care of this case: // we should take care of this case:
@ -66,7 +105,7 @@ class TurnIntoOptionAction extends CustomActionCell {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
final node = editorState.getNodeAtPath(selection.start.path); final node = widget.editorState.getNodeAtPath(selection.start.path);
if (node == null) { if (node == null) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
@ -78,7 +117,7 @@ class TurnIntoOptionAction extends CustomActionCell {
} }
bool _hasNonSupportedTypes(Selection selection) { bool _hasNonSupportedTypes(Selection selection) {
final nodes = editorState.getNodesInSelection(selection); final nodes = widget.editorState.getNodesInSelection(selection);
if (nodes.isEmpty) { if (nodes.isEmpty) {
return false; return false;
} }

View File

@ -49,7 +49,7 @@ final headingsToolbarItem = ToolbarItem(
], ],
), ),
); );
return _HeadingPopup( return HeadingPopup(
currentLevel: isHighlight ? level : -1, currentLevel: isHighlight ? level : -1,
highlightColor: highlightColor, highlightColor: highlightColor,
child: child, child: child,
@ -60,9 +60,9 @@ final headingsToolbarItem = ToolbarItem(
? ParagraphBlockKeys.type ? ParagraphBlockKeys.type
: HeadingBlockKeys.type; : HeadingBlockKeys.type;
await editorState.formatNode( if (type == HeadingBlockKeys.type) {
selection, // from paragraph to heading
(node) => node.copyWith( final newNode = node.copyWith(
type: type, type: type,
attributes: { attributes: {
HeadingBlockKeys.level: newLevel, HeadingBlockKeys.level: newLevel,
@ -72,15 +72,41 @@ final headingsToolbarItem = ToolbarItem(
node.attributes[blockComponentTextDirection], node.attributes[blockComponentTextDirection],
blockComponentDelta: delta, blockComponentDelta: delta,
}, },
), );
); final children = node.children.map((child) => child.copyWith());
final transaction = editorState.transaction;
transaction.insertNodes(
selection.start.path.next,
[newNode, ...children],
);
transaction.deleteNode(node);
await editorState.apply(transaction);
} else {
// from heading to paragraph
await editorState.formatNode(
selection,
(node) => node.copyWith(
type: type,
attributes: {
HeadingBlockKeys.level: newLevel,
blockComponentBackgroundColor:
node.attributes[blockComponentBackgroundColor],
blockComponentTextDirection:
node.attributes[blockComponentTextDirection],
blockComponentDelta: delta,
},
),
);
}
}, },
); );
}, },
); );
class _HeadingPopup extends StatelessWidget { class HeadingPopup extends StatelessWidget {
const _HeadingPopup({ const HeadingPopup({
super.key,
required this.currentLevel, required this.currentLevel,
required this.highlightColor, required this.highlightColor,
required this.onLevelChanged, required this.onLevelChanged,
@ -144,7 +170,7 @@ class _HeadingButtons extends StatelessWidget {
final svg = data.$1; final svg = data.$1;
final message = data.$2; final message = data.$2;
return [ return [
_HeadingButton( HeadingButton(
icon: svg, icon: svg,
tooltip: message, tooltip: message,
onTap: () => onLevelChanged(index + 1), onTap: () => onLevelChanged(index + 1),
@ -163,8 +189,9 @@ class _HeadingButtons extends StatelessWidget {
} }
} }
class _HeadingButton extends StatelessWidget { class HeadingButton extends StatelessWidget {
const _HeadingButton({ const HeadingButton({
super.key,
required this.icon, required this.icon,
required this.tooltip, required this.tooltip,
required this.onTap, required this.onTap,

View File

@ -1,4 +1,5 @@
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/toggle/toggle_block_component.dart';
import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor/appflowy_editor.dart';
/// Convert '# ' to bulleted list /// Convert '# ' to bulleted list
@ -35,6 +36,7 @@ CharacterShortcutEvent customFormatSignToHeading = CharacterShortcutEvent(
level: numberOfSign, level: numberOfSign,
delta: delta.compose(Delta()..delete(numberOfSign)), delta: delta.compose(Delta()..delete(numberOfSign)),
collapsed: collapsed ?? false, collapsed: collapsed ?? false,
children: node.children.map((child) => child.copyWith()),
), ),
]; ];
} }

View File

@ -180,6 +180,31 @@ class _ToggleListBlockComponentWidgetState
: buildComponentWithChildren(context); : buildComponentWithChildren(context);
} }
@override
Widget buildComponentWithChildren(BuildContext context) {
return Stack(
children: [
if (backgroundColor != Colors.transparent)
Positioned.fill(
left: cachedLeft,
top: padding.top,
child: Container(
width: double.infinity,
color: backgroundColor,
),
),
NestedListWidget(
indentPadding: indentPadding,
child: buildComponent(context),
children: editorState.renderer.buildList(
context,
widget.node.children,
),
),
],
);
}
@override @override
Widget buildComponent( Widget buildComponent(
BuildContext context, { BuildContext context, {
@ -190,9 +215,6 @@ class _ToggleListBlockComponentWidgetState
); );
Widget child = Container( Widget child = Container(
color: withBackgroundColor || backgroundColor != Colors.transparent
? backgroundColor
: null,
width: double.infinity, width: double.infinity,
alignment: alignment, alignment: alignment,
child: Row( child: Row(
@ -208,12 +230,6 @@ class _ToggleListBlockComponentWidgetState
), ),
); );
child = Padding(
key: blockComponentKey,
padding: padding,
child: child,
);
child = BlockSelectionContainer( child = BlockSelectionContainer(
node: node, node: node,
delegate: this, delegate: this,
@ -225,6 +241,18 @@ class _ToggleListBlockComponentWidgetState
child: child, child: child,
); );
child = Padding(
padding: padding,
child: Container(
key: blockComponentKey,
color: withBackgroundColor ||
(backgroundColor != Colors.transparent && collapsed)
? backgroundColor
: null,
child: child,
),
);
if (widget.showActions && widget.actionBuilder != null) { if (widget.showActions && widget.actionBuilder != null) {
child = BlockComponentActionWrapper( child = BlockComponentActionWrapper(
node: node, node: node,
@ -293,16 +321,16 @@ class _ToggleListBlockComponentWidgetState
minHeight: buttonHeight, minHeight: buttonHeight,
), ),
padding: EdgeInsets.only(top: top, right: 4.0), padding: EdgeInsets.only(top: top, right: 4.0),
child: AnimatedRotation( child: FlowyIconButton(
turns: collapsed ? 0.0 : 0.25, width: 20.0,
duration: const Duration(milliseconds: 200), onPressed: onCollapsed,
child: FlowyIconButton( icon: AnimatedRotation(
width: 20.0, turns: collapsed ? 0.0 : 0.25,
icon: const Icon( duration: const Duration(milliseconds: 200),
child: const Icon(
Icons.arrow_right, Icons.arrow_right,
size: 18.0, size: 18.0,
), ),
onPressed: onCollapsed,
), ),
), ),
); );

View File

@ -61,8 +61,8 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
path: "." path: "."
ref: eccb244 ref: "2903792"
resolved-ref: eccb24452a451c734bc2aeae56c1fd81398d849c resolved-ref: "2903792fa319e1b4077164eeb684f6e8d1c63e27"
url: "https://github.com/AppFlowy-IO/appflowy-editor.git" url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
source: git source: git
version: "4.0.0" version: "4.0.0"

View File

@ -172,7 +172,7 @@ dependency_overrides:
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: "eccb244" ref: "2903792"
appflowy_editor_plugins: appflowy_editor_plugins:
git: git:

View File

@ -2495,7 +2495,7 @@
"spaceIcon": "Icon", "spaceIcon": "Icon",
"dangerZone": "Danger Zone", "dangerZone": "Danger Zone",
"unableToDeleteLastSpace": "Unable to delete the last Space", "unableToDeleteLastSpace": "Unable to delete the last Space",
"unableToDeleteSpaceNotCreatedByYou": "Unable to delete Spaces created by others", "unableToDeleteSpaceNotCreatedByYou": "Unable to delete spaces created by others",
"enableSpacesForYourWorkspace": "Enable Spaces for your workspace", "enableSpacesForYourWorkspace": "Enable Spaces for your workspace",
"title": "Spaces", "title": "Spaces",
"defaultSpaceName": "General", "defaultSpaceName": "General",