mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-11-02 11:04:02 +00:00
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:
parent
54096b391f
commit
82effbf8e4
@ -1,6 +1,8 @@
|
||||
import 'package:appflowy/generated/locale_keys.g.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:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
@ -60,6 +62,50 @@ void main() {
|
||||
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');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -231,7 +231,6 @@ class _DocumentPageState extends State<DocumentPage>
|
||||
|
||||
final Path? path = _getPathFromAction(action, editorState);
|
||||
if (path != null) {
|
||||
debugPrint('jump to block: $path');
|
||||
editorState.updateSelectionWithReason(
|
||||
Selection.collapsed(Position(path: path)),
|
||||
);
|
||||
|
||||
@ -134,12 +134,19 @@ void _customBlockOptionActions(
|
||||
);
|
||||
|
||||
builder.actionBuilder = (context, state) {
|
||||
final top = builder.configuration.padding(context.node).top;
|
||||
final padding = context.node.type == HeadingBlockKeys.type
|
||||
? EdgeInsets.only(top: top + 8.0)
|
||||
: EdgeInsets.only(top: top + 2.0);
|
||||
double top = builder.configuration.padding(context.node).top;
|
||||
final type = context.node.type;
|
||||
final level = context.node.attributes[HeadingBlockKeys.level] ?? 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(
|
||||
padding: padding,
|
||||
padding: EdgeInsets.only(top: top),
|
||||
child: BlockActionList(
|
||||
blockComponentContext: context,
|
||||
blockComponentState: state,
|
||||
|
||||
@ -9,7 +9,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import 'drag_to_reorder/draggable_option_button.dart';
|
||||
|
||||
class BlockOptionButton extends StatelessWidget {
|
||||
class BlockOptionButton extends StatefulWidget {
|
||||
const BlockOptionButton({
|
||||
super.key,
|
||||
required this.blockComponentContext,
|
||||
@ -25,6 +25,16 @@ class BlockOptionButton extends StatelessWidget {
|
||||
final EditorState editorState;
|
||||
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
|
||||
Widget build(BuildContext context) {
|
||||
final direction =
|
||||
@ -34,8 +44,8 @@ class BlockOptionButton extends StatelessWidget {
|
||||
: PopoverDirection.leftWithCenterAligned;
|
||||
return BlocProvider(
|
||||
create: (context) => BlockActionOptionCubit(
|
||||
editorState: editorState,
|
||||
blockComponentBuilder: blockComponentBuilder,
|
||||
editorState: widget.editorState,
|
||||
blockComponentBuilder: widget.blockComponentBuilder,
|
||||
),
|
||||
child: BlocBuilder<BlockActionOptionCubit, BlockActionOptionState>(
|
||||
builder: (context, _) => PopoverActionList<PopoverAction>(
|
||||
@ -55,30 +65,41 @@ class BlockOptionButton extends StatelessWidget {
|
||||
),
|
||||
buildChild: (controller) => DraggableOptionButton(
|
||||
controller: controller,
|
||||
editorState: editorState,
|
||||
blockComponentContext: blockComponentContext,
|
||||
blockComponentBuilder: blockComponentBuilder,
|
||||
editorState: widget.editorState,
|
||||
blockComponentContext: widget.blockComponentContext,
|
||||
blockComponentBuilder: widget.blockComponentBuilder,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
mutex.dispose();
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
List<PopoverAction> _buildPopoverActions(BuildContext context) {
|
||||
return actions.map((e) {
|
||||
return widget.actions.map((e) {
|
||||
switch (e) {
|
||||
case OptionAction.divider:
|
||||
return DividerOptionAction();
|
||||
case OptionAction.color:
|
||||
return ColorOptionAction(editorState: editorState);
|
||||
return ColorOptionAction(
|
||||
editorState: widget.editorState,
|
||||
mutex: mutex,
|
||||
);
|
||||
case OptionAction.align:
|
||||
return AlignOptionAction(editorState: editorState);
|
||||
return AlignOptionAction(editorState: widget.editorState);
|
||||
case OptionAction.depth:
|
||||
return DepthOptionAction(editorState: editorState);
|
||||
return DepthOptionAction(editorState: widget.editorState);
|
||||
case OptionAction.turnInto:
|
||||
return TurnIntoOptionAction(
|
||||
editorState: editorState,
|
||||
blockComponentBuilder: blockComponentBuilder,
|
||||
editorState: widget.editorState,
|
||||
blockComponentBuilder: widget.blockComponentBuilder,
|
||||
mutex: mutex,
|
||||
);
|
||||
default:
|
||||
return OptionActionWrapper(e);
|
||||
@ -88,15 +109,17 @@ class BlockOptionButton extends StatelessWidget {
|
||||
|
||||
void _onPopoverBuilder() {
|
||||
keepEditorFocusNotifier.increase();
|
||||
blockComponentState.alwaysShowActions = true;
|
||||
widget.blockComponentState.alwaysShowActions = true;
|
||||
}
|
||||
|
||||
void _onPopoverClosed(BuildContext context) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
editorState.selectionType = null;
|
||||
editorState.selection = null;
|
||||
blockComponentState.alwaysShowActions = false;
|
||||
widget.editorState.selectionType = null;
|
||||
widget.editorState.selection = null;
|
||||
widget.blockComponentState.alwaysShowActions = false;
|
||||
});
|
||||
|
||||
PopoverContainer.maybeOf(context)?.closeAll();
|
||||
}
|
||||
|
||||
void _onActionSelected(
|
||||
@ -110,7 +133,7 @@ class BlockOptionButton extends StatelessWidget {
|
||||
|
||||
context.read<BlockActionOptionCubit>().handleAction(
|
||||
action.inner,
|
||||
blockComponentContext.node,
|
||||
widget.blockComponentContext.node,
|
||||
);
|
||||
controller.close();
|
||||
}
|
||||
|
||||
@ -389,6 +389,14 @@ class BlockActionOptionCubit extends Cubit<BlockActionOptionState> {
|
||||
]);
|
||||
if (afterSelection != null) {
|
||||
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);
|
||||
|
||||
|
||||
@ -13,10 +13,12 @@ const optionActionColorDefaultColor = 'appflowy_theme_default_color';
|
||||
class ColorOptionAction extends CustomActionCell {
|
||||
ColorOptionAction({
|
||||
required this.editorState,
|
||||
required this.mutex,
|
||||
});
|
||||
|
||||
final EditorState editorState;
|
||||
final PopoverController innerController = PopoverController();
|
||||
final PopoverMutex mutex;
|
||||
|
||||
@override
|
||||
Widget buildWithContext(
|
||||
@ -24,16 +26,49 @@ class ColorOptionAction extends CustomActionCell {
|
||||
PopoverController controller,
|
||||
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(
|
||||
asBarrier: true,
|
||||
controller: innerController,
|
||||
mutex: mutex,
|
||||
popupBuilder: (context) => _buildColorOptionMenu(
|
||||
context,
|
||||
controller,
|
||||
),
|
||||
mutex: widget.mutex,
|
||||
popupBuilder: (context) {
|
||||
isOpen = true;
|
||||
return _buildColorOptionMenu(
|
||||
context,
|
||||
widget.controller,
|
||||
);
|
||||
},
|
||||
onClose: () => isOpen = false,
|
||||
direction: PopoverDirection.rightWithCenterAligned,
|
||||
offset: const Offset(10, 0),
|
||||
animationDuration: Durations.short3,
|
||||
beginScaleFactor: 1.0,
|
||||
beginOpacity: 0.8,
|
||||
@ -45,7 +80,9 @@ class ColorOptionAction extends CustomActionCell {
|
||||
),
|
||||
name: LocaleKeys.document_plugins_optionAction_color.tr(),
|
||||
onTap: () {
|
||||
innerController.show();
|
||||
if (!isOpen) {
|
||||
innerController.show();
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
@ -55,12 +92,12 @@ class ColorOptionAction extends CustomActionCell {
|
||||
BuildContext context,
|
||||
PopoverController controller,
|
||||
) {
|
||||
final selection = editorState.selection?.normalized;
|
||||
final selection = widget.editorState.selection?.normalized;
|
||||
if (selection == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final node = editorState.getNodeAtPath(selection.start.path);
|
||||
final node = widget.editorState.getNodeAtPath(selection.start.path);
|
||||
if (node == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
@ -73,11 +110,11 @@ class ColorOptionAction extends CustomActionCell {
|
||||
Node node,
|
||||
PopoverController controller,
|
||||
) {
|
||||
final selection = editorState.selection?.normalized;
|
||||
final selection = widget.editorState.selection?.normalized;
|
||||
if (selection == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
final node = editorState.getNodeAtPath(selection.start.path);
|
||||
final node = widget.editorState.getNodeAtPath(selection.start.path);
|
||||
if (node == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
@ -110,11 +147,11 @@ class ColorOptionAction extends CustomActionCell {
|
||||
color: AFThemeExtension.of(context).onBackground,
|
||||
),
|
||||
onTap: (option, index) async {
|
||||
final transaction = editorState.transaction;
|
||||
final transaction = widget.editorState.transaction;
|
||||
transaction.updateNode(node, {
|
||||
blockComponentBackgroundColor: option.id,
|
||||
});
|
||||
await editorState.apply(transaction);
|
||||
await widget.editorState.apply(transaction);
|
||||
|
||||
innerController.close();
|
||||
controller.close();
|
||||
|
||||
@ -15,11 +15,13 @@ class TurnIntoOptionAction extends CustomActionCell {
|
||||
TurnIntoOptionAction({
|
||||
required this.editorState,
|
||||
required this.blockComponentBuilder,
|
||||
required this.mutex,
|
||||
});
|
||||
|
||||
final EditorState editorState;
|
||||
final Map<String, BlockComponentBuilder> blockComponentBuilder;
|
||||
final PopoverController innerController = PopoverController();
|
||||
final PopoverMutex mutex;
|
||||
|
||||
@override
|
||||
Widget buildWithContext(
|
||||
@ -27,21 +29,54 @@ class TurnIntoOptionAction extends CustomActionCell {
|
||||
PopoverController controller,
|
||||
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(
|
||||
asBarrier: true,
|
||||
controller: innerController,
|
||||
mutex: mutex,
|
||||
popupBuilder: (context) => BlocProvider<BlockActionOptionCubit>(
|
||||
create: (_) => BlockActionOptionCubit(
|
||||
editorState: editorState,
|
||||
blockComponentBuilder: blockComponentBuilder,
|
||||
),
|
||||
child: BlocBuilder<BlockActionOptionCubit, BlockActionOptionState>(
|
||||
builder: (context, _) => _buildTurnIntoOptionMenu(context),
|
||||
),
|
||||
),
|
||||
mutex: widget.mutex,
|
||||
popupBuilder: (context) {
|
||||
isOpen = true;
|
||||
return BlocProvider<BlockActionOptionCubit>(
|
||||
create: (context) => BlockActionOptionCubit(
|
||||
editorState: widget.editorState,
|
||||
blockComponentBuilder: widget.blockComponentBuilder,
|
||||
),
|
||||
child: BlocBuilder<BlockActionOptionCubit, BlockActionOptionState>(
|
||||
builder: (context, _) => _buildTurnIntoOptionMenu(context),
|
||||
),
|
||||
);
|
||||
},
|
||||
onClose: () => isOpen = false,
|
||||
direction: PopoverDirection.rightWithCenterAligned,
|
||||
offset: const Offset(10, 0),
|
||||
animationDuration: Durations.short3,
|
||||
beginScaleFactor: 1.0,
|
||||
beginOpacity: 0.8,
|
||||
@ -50,13 +85,17 @@ class TurnIntoOptionAction extends CustomActionCell {
|
||||
// todo(lucas): replace the svg with the correct one
|
||||
leftIcon: const FlowySvg(FlowySvgs.turninto_s),
|
||||
name: LocaleKeys.document_plugins_optionAction_turnInto.tr(),
|
||||
onTap: innerController.show,
|
||||
onTap: () {
|
||||
if (!isOpen) {
|
||||
innerController.show();
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
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 will be the start from the current block and end at the last child block.
|
||||
// we should take care of this case:
|
||||
@ -66,7 +105,7 @@ class TurnIntoOptionAction extends CustomActionCell {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final node = editorState.getNodeAtPath(selection.start.path);
|
||||
final node = widget.editorState.getNodeAtPath(selection.start.path);
|
||||
if (node == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
@ -78,7 +117,7 @@ class TurnIntoOptionAction extends CustomActionCell {
|
||||
}
|
||||
|
||||
bool _hasNonSupportedTypes(Selection selection) {
|
||||
final nodes = editorState.getNodesInSelection(selection);
|
||||
final nodes = widget.editorState.getNodesInSelection(selection);
|
||||
if (nodes.isEmpty) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ final headingsToolbarItem = ToolbarItem(
|
||||
],
|
||||
),
|
||||
);
|
||||
return _HeadingPopup(
|
||||
return HeadingPopup(
|
||||
currentLevel: isHighlight ? level : -1,
|
||||
highlightColor: highlightColor,
|
||||
child: child,
|
||||
@ -60,9 +60,9 @@ final headingsToolbarItem = ToolbarItem(
|
||||
? ParagraphBlockKeys.type
|
||||
: HeadingBlockKeys.type;
|
||||
|
||||
await editorState.formatNode(
|
||||
selection,
|
||||
(node) => node.copyWith(
|
||||
if (type == HeadingBlockKeys.type) {
|
||||
// from paragraph to heading
|
||||
final newNode = node.copyWith(
|
||||
type: type,
|
||||
attributes: {
|
||||
HeadingBlockKeys.level: newLevel,
|
||||
@ -72,15 +72,41 @@ final headingsToolbarItem = ToolbarItem(
|
||||
node.attributes[blockComponentTextDirection],
|
||||
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 {
|
||||
const _HeadingPopup({
|
||||
class HeadingPopup extends StatelessWidget {
|
||||
const HeadingPopup({
|
||||
super.key,
|
||||
required this.currentLevel,
|
||||
required this.highlightColor,
|
||||
required this.onLevelChanged,
|
||||
@ -144,7 +170,7 @@ class _HeadingButtons extends StatelessWidget {
|
||||
final svg = data.$1;
|
||||
final message = data.$2;
|
||||
return [
|
||||
_HeadingButton(
|
||||
HeadingButton(
|
||||
icon: svg,
|
||||
tooltip: message,
|
||||
onTap: () => onLevelChanged(index + 1),
|
||||
@ -163,8 +189,9 @@ class _HeadingButtons extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _HeadingButton extends StatelessWidget {
|
||||
const _HeadingButton({
|
||||
class HeadingButton extends StatelessWidget {
|
||||
const HeadingButton({
|
||||
super.key,
|
||||
required this.icon,
|
||||
required this.tooltip,
|
||||
required this.onTap,
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
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';
|
||||
|
||||
/// Convert '# ' to bulleted list
|
||||
@ -35,6 +36,7 @@ CharacterShortcutEvent customFormatSignToHeading = CharacterShortcutEvent(
|
||||
level: numberOfSign,
|
||||
delta: delta.compose(Delta()..delete(numberOfSign)),
|
||||
collapsed: collapsed ?? false,
|
||||
children: node.children.map((child) => child.copyWith()),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@ -180,6 +180,31 @@ class _ToggleListBlockComponentWidgetState
|
||||
: 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
|
||||
Widget buildComponent(
|
||||
BuildContext context, {
|
||||
@ -190,9 +215,6 @@ class _ToggleListBlockComponentWidgetState
|
||||
);
|
||||
|
||||
Widget child = Container(
|
||||
color: withBackgroundColor || backgroundColor != Colors.transparent
|
||||
? backgroundColor
|
||||
: null,
|
||||
width: double.infinity,
|
||||
alignment: alignment,
|
||||
child: Row(
|
||||
@ -208,12 +230,6 @@ class _ToggleListBlockComponentWidgetState
|
||||
),
|
||||
);
|
||||
|
||||
child = Padding(
|
||||
key: blockComponentKey,
|
||||
padding: padding,
|
||||
child: child,
|
||||
);
|
||||
|
||||
child = BlockSelectionContainer(
|
||||
node: node,
|
||||
delegate: this,
|
||||
@ -225,6 +241,18 @@ class _ToggleListBlockComponentWidgetState
|
||||
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) {
|
||||
child = BlockComponentActionWrapper(
|
||||
node: node,
|
||||
@ -293,16 +321,16 @@ class _ToggleListBlockComponentWidgetState
|
||||
minHeight: buttonHeight,
|
||||
),
|
||||
padding: EdgeInsets.only(top: top, right: 4.0),
|
||||
child: AnimatedRotation(
|
||||
turns: collapsed ? 0.0 : 0.25,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
child: FlowyIconButton(
|
||||
width: 20.0,
|
||||
icon: const Icon(
|
||||
child: FlowyIconButton(
|
||||
width: 20.0,
|
||||
onPressed: onCollapsed,
|
||||
icon: AnimatedRotation(
|
||||
turns: collapsed ? 0.0 : 0.25,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
child: const Icon(
|
||||
Icons.arrow_right,
|
||||
size: 18.0,
|
||||
),
|
||||
onPressed: onCollapsed,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -61,8 +61,8 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: eccb244
|
||||
resolved-ref: eccb24452a451c734bc2aeae56c1fd81398d849c
|
||||
ref: "2903792"
|
||||
resolved-ref: "2903792fa319e1b4077164eeb684f6e8d1c63e27"
|
||||
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
||||
source: git
|
||||
version: "4.0.0"
|
||||
|
||||
@ -172,7 +172,7 @@ dependency_overrides:
|
||||
appflowy_editor:
|
||||
git:
|
||||
url: https://github.com/AppFlowy-IO/appflowy-editor.git
|
||||
ref: "eccb244"
|
||||
ref: "2903792"
|
||||
|
||||
appflowy_editor_plugins:
|
||||
git:
|
||||
|
||||
@ -2495,7 +2495,7 @@
|
||||
"spaceIcon": "Icon",
|
||||
"dangerZone": "Danger Zone",
|
||||
"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",
|
||||
"title": "Spaces",
|
||||
"defaultSpaceName": "General",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user